Vous êtes sur la page 1sur 45

Introduction aux méthodes numériques

Environnement MATLAB

Antoine Bertout

ENSIP - 1ère année TC

2020–2021

1 / 42
Objectifs du jour

Présenter l’environnement MATLAB et le langage MATLAB et ses


spécificités (comme Python ? syntaxe, sémantique, etc.)
Savoir écrire un algo en MATLAB
Optimiser l’utilisation de MATLAB grâce à la pré-allocation et la
vectorisation des programmes
...en espérant qu’il vous en reste un vague souvenir avant les TP

2 / 42
Écosystèmes de MATLAB et Python

EDIs
Pyzo, jupyter notebook,
Spyder,etc.

Noyau de MATLAB
Noyau de Python
- EDI
- langage
- langage
de programmation
de programmation
- interpréteur
- interpréteur
- bibliothèque
- large bibliothèque
standard réduite
standard
- éditeur d'interface
graphique Numpy Matplotlib

Etc.

3 / 42
MATLAB vs Python

MATLAB est à la fois le nom du logiciel et le nom du langage qu’il


implémente.
MATLAB n’est pas généraliste contrairement à Python, il est
nativement plus adaptés aux calculs numériques.
MATLAB c’est propriétaire...et cher !
Mais GNU Octave est un clone libre, gratuit, multi-OS et
équivalent pour 99% de ce que nous allons faire !
MATLAB ⇔ Python + bibliothèques numériques (Numpy, Scipy,
Matplotlib, etc.)

4 / 42
Interface MATLAB
Dans la même fenêtre, on retrouve :
un interpréteur nommé Command Window
>> 8 + 5
ans = 13

ans est l’équivalent de _ en Python.


un éditeur
un Workspace où apparaissent les variables manipulées que l’on
peut modifier (RAZ avec clear all).
un navigateur avec une notion de chemins
Attention !

Les noms des fonctions ne sont pas réservés...

>> sqrt(5)
ans = 2.2361
>> sqrt = 3
>> sqrt(4) Index exceeds matrix dimensions.

5 / 42
Variables et types

Dans MATLAB, la structure de données de base est un tableau


multidimensionnel. La plupart des opérations manipulent et
retournent ces tableaux à la manière des opérations matricielles de
l’algèbre linéaire. Nous parlerons de matrices pour ces tableaux.
Nous appellerons vecteurs les matrices à une dimension mais dans
MATLAB tout est représenté comme des matrices.
Par défaut, tous les types numériques sont des flottants double
précision (64 bits)
Les chaînes de caractères sont des matrices de caractères
'Salut !' que l’on entoure de guillemets simples uniquement.
Les booléens sont de type logical et valent 1 (vrai) ou 0 (faux).
La matrice est l’équivalent de la liste en Python, il n’y a pas de
tuple.
Toutes les matrices sont modifiables, quelle que soit leur type,
même les chaînes de caractères !

6 / 42
Typage

Comme avec Python, il n’est pas nécessaire de déclarer le type de


la variable utilisée et il n’y pas de type attaché au nom de la
variable a = 5; a = 'Z'
2.^ ('ENSIP' - 69) ⇒ pas de problème, ça s’exécute. C’est
bizarre, mais déterministe.
Par contre les dimensions des matrices sont vérifiées, elles
doivent être compatibles.
Le typage est très léger avec MATLAB...

7 / 42
Matrices

Déclarations d’un vecteur 1x5

mat = [1 3 5 7 9]
mat = [1, 3, 5, 7, 9] %
mat = [1:2:9] % début:pas:fin

Déclaration d’une matrice 2x3 avec le point virgule

mat = [1 3 5 ; 7 9 11]

Concaténation

a = [6 7]
b = [4 5 a]
c = [4 5;b]

8 / 42
Matrices : indiçage et assignation

Indiçage et sous-parties (slices) de matrices

mat(2,3) % élément ligne 2 colonne 3


mat(1,:) % première ligne
mat(:,1) % première colonne
mat([1 3], [1 4])% éléments (1,1),(1,4),(3,1),(3,4)
mat(2:end,:) % mat sans la première ligne

Le mot clé end dans vec(end) correspond à l’utilisation de


vec[-1] en Python. Il pointe vers le dernier élément de la dimension.

Attention
Avec MATLAB et contrairement à Python les indices ne commencent
pas à 0 mais à 1 et l’indiçage se fait avec les parenthèses et non les
crochets.

9 / 42
Matrices : indiçage et assignation

Assignation

a(:,1) = 99
a(:,1) = [99 98 97]
a(a>98) = 5 %seuil

Logical
a > 98 produit une matrice de type logical et non un double !

10 / 42
Matrices : indiçage et assignation

Assignation

a(:,1) = 99
a(:,1) = [99 98 97]
a(a>98) = 5 %seuil

Logical
a > 98 produit une matrice de type logical et non un double !

a([0 0 1]) error subscripts must be either integers or logical

10 / 42
Bornes
Vérification des bornes
Comme Python, MATLAB déclenche une erreur lorsque vous essayez
de lire des cellules en dehors des bornes d’une matrice.

a = [5 9 10 9]
>> v = a(5)
Index exceeds matrix dimensions.
>> a(-1)
Subscript indices must either be real positive integers...

Extensibilité
Bien que ça ne soit généralement pas conseillé, et contrairement à
Python, MATLAB autorise d’assigner une valeur dans une cellule qui
n’existe pas et étend automatiquement la matrice.

>> a(5) = 3
a = 5 9 10 9 3
>> a(10) = 1
a = 5 9 10 9 3 0 0 0 0 1
11 / 42
Sémantique des assignations

Attention
Dans MATLAB, les structures de données sont passées par valeur et
non par par référence comme en Python. Les ”slices” copient les
parties des tableaux.
MATLAB Python

>> a = [3 5 7] >>> a = [3, 5, 7]


>> v = a >>> v = a
>> v(3) = 1 >>> v[2] = 1
v = [3 5 1] v = [3, 5, 1]
>> a >>> a
a = [3 5 7] a = [3, 5, 1]

12 / 42
Concision des opérations matricielles
Exemple : Effet miroir sur une image

MATLAB

A = imread('arles.png');
B = A(:,end:-1:1,:);
image(B);

Python

import matplotlib.pyplot as plt


from PIL import Image ↓

im = load_image("arles.png")
im2 = im.copy()
for i in range(im2.size[1]):
for j in range(im2.size[0]):
r, v, b = im.getpixel((i, im.size[0]-1-j)
im2.putpixel((i, j)), (r, v, b))
plt.imshow(image)
plt.show() 13 / 42
Structures de contrôles : Boucles
Factorielle en boucle

Boucle for :
nmax = 5;
for n = 1:nmax
nFact = nFact * n
end

Syntaxe d’un pas différent de 1 ⇒ debut:pas:fin


(range(debut,fin,pas) en Python)
Itérer directement sur les éléments d’un vecteur for elem=vec
(for elem in vec en Python)
Boule while :
nFact = 1;
n = 1;
while n < nmax
n = n + 1
nFact = nFact * n
end 14 / 42
Structures de contrôles

Délimitation des blocs


Contrairement à Python, MATLAB n’utilise pas l’indentation pour
délimiter ses blocs (boucles,conditions, etc.) mais le mot-clé end.
Le programme suivant s’exécute sans problème.

for inum = 1:100 fizzbuzz =''; if mod(inum,3)==0


fizzbuzz=[fizzbuzz 'Fizz'];end ;if mod(inum ,5)== 0
fizzbuzz=[fizzbuzz 'Buzz']end;if isempty(fizzbuzz)
disp(inum) else disp(fizzbuzz)end end

Gardez le bon réflexe d’indenter votre code pour sa lisibilité.

15 / 42
Structures de contrôles
Affectation après...
Contrairement à Python, il n’est pas possible d’utiliser les opérateurs
d’affectation après addition (+=), multiplication(*=), etc. tel que
nFactorial *= n.
Conditions

a = randi(100, 1);%nombre aléatoire entre 1 et 100


if a < 30
disp('petit')
elseif a < 80
disp('moyen')
else
disp('grand')
end

Affichage
La fonction disp est l’équivalent du print. Le plus simple pour
afficher le résultat d’un calcul c’est d’omettre le point virgule à la fin
de l’instruction.
16 / 42
Structures de contrôles

Lorsque vous traitez un ensemble de valeurs prédéfinies, le switch


est une alternative élégante. Il fonctionne également avec les
scalaires. Le switch n’existe pas en Python.

method = 'secant';
switch method
case 'dicho'
disp('Method convergence is linear')
case {'newton','brent'}
disp('Method convergence is quadratic')
otherwise
disp('Unknown method.')
end

17 / 42
Opérateurs logiques
MATLAB Python signification
| | OU logique
& & ET logique
~ not NON logique
&& and ET logique court-circuit
|| or OU logique court-circuit
etc.
l’évaluation de 0 && n’importe quoi est court-circuitée en 0 (faux).
l’évaluation de 1 || n’importe quoi est court-circuitée en 1 (vrai).
Efficacité
Pour évaluer des conditions dans vos structures de contrôles, vous
devez utiliser des structures de type court-circuit.

>> u = [0 0 1 1 0 1];
>> v = [0 1 1 0 0 1];
>> u | v
ans = 0 1 1 1 0 1
>> if 1 || 0
ans = 1
18 / 42
Opérateurs matriciels
On retrouve les opérateurs usuelles + - * etc., cependant,

il est primordial de distinguer les opérations matricielles des


opérations par éléments :
Par défaut les opérateurs concernent les opérations matricielles,
par exemple, la multiplication de deux matrices a et b s’écrit
a * b
Pour effectuer une opération élément par élément (terme par
terme) il faut utiliser la notation pointée, comme pour multiplier
tous les éléments de deux vecteurs deux à deux avec a .* b
La notation pointée ne concerne que la multiplication, la division
et l’élévation à la puissance.

>>A = [1 0 3];B = [2 3 7];C = A.*B


C = [2 0 21]
>>C = A * B
Error using *, Inner matrix dimensions must agree.
>>C = A * B'
23

L’opérateur ' permet de transposer une matrice. 19 / 42


Fonctions et scripts

Vocabulaire
L’extension des fichiers MATLAB est .m (quand Python c’est .py),
par défaut un fichier MATLAB est un script.
Une fonction MATLAB correspond à une fonction ou une
procédure, comme en Python. Dans la version de MATLAB utilisée
en cours, il est obligatoire de définir une fonction dans un fichier
.m à part du même nom.
La syntaxe est
function [y1,...,yN] = myfun(x1,...,xM) où myfun
est le nom de la fonction, les yi les sorties (encapsulées dans un
vecteur) et les xi les entrées.
Les fonctions anonymes adaptées à l’écriture de fonctions
simples (comme les fonctions au sens mathématique) tel que
sqr = @(x) x.^2
>> sqr(5)%ans = 25

20 / 42
Fonctions
Exemple de fonction classique
Approximation
 de π par la formule de Leibniz :
π ≈ 4 × 1 − 3 + 15 − 17 · · · ± 2n+1
1 1
.

function [mypi] = approxpi(n)


mypi = 0 def approx_pi(n):
for i=0:n-1 pi = 0
if mod(i,2) for i in range(n):
mypi = mypi - 1/(2*i+1) if i%2:
else pi += -1/(2*i+1)
mypi = mypi + 1/(2*i+1) else:
end pi += 1/(2*i+1)
end return 4 * pi
mypi = mypi * 4
Le modulo en MATLAB ne s’écrit pas a%b (c’est le commentaire) comme
en Python mais mod(a,b).
Le mot clé return ne peut retourner de valeur, il quitte uniquement la
fonction.
La fonction renvoie la dernière valeur connue de l’argument.
Question. Pourquoi ai-je nommé ma variable mypi et non pi ? 21 / 42
Fonctions standards
La plupart des fonctions mathématiques de MATLAB comme sin,
cos, log et beaucoup d’autres fonctionnent quelque soit la taille
de leur argument. Si A est une matrice de taille quelconque alors
B = sin(A) est une matrice de même taille (
B(i,j) == sin(A(i,j))
Certaines fonctions s’appliquent sur des vecteurs et retournent
des scalaires
Si elles sont appliquées sur des matrices à plusieurs dimensions,
un scalaire est retourné par dimension

Fonction max Fonction sum

x = [1, 4, 8, -1, 2];


max(x) == 8 A = rand(2, 5, 4)
y = [2; 7; -2; -3; 2]; sum(sum(sum(A)))
max(y) == 7 sum(A(:)) % Flatten
A = [1, 3, 2; -4, 5, -1];
max(A) == [1 5 2]

22 / 42
Représentation mémoire

Column-major order
Bien qu’il s’agisse de structures de données en deux dimensions
logiques, les matrices en MATLAB sont en fait représentées en interne
en une dimension, linéarisées, colonne par colonne.1
 
8 1 6
La matrice est stockée en mémoire comme un vecteur
3 5 7
colonne
 
8 Ouf !
3
 
1 La plupart du temps vous n’aurez pas à vous en
 
5 soucier mais il faut le garder à l’esprit. Par
 
6 exemple, lorsque vous aplatissez une matrice
avec l’opérateur :
7

1 on parle de column-major order à la différence de Numpy qui est row-major


23 / 42
Graphique
MATLAB intègre des fonctions graphiques qui permettent
d’afficher facilement des courbes (2D et 3D)
C’est très pratique en méthodes numériques
Si vous avez réalisé le TP de programmation sur la méthode de
Monte Carlo vous savez déjà tracer des courbes dans MATLAB (la
bibliothèque Python Matplotlib a en effet copié exactement la
syntaxe de MATLAB)
2

x = 0:pi/10:2*pi; 1.5

y1 = 2*sin(x); 1

y2 = sin(2*x); 0.5

y3 = sin(x+0.5); 0

-0.5

plot(x,y1,'g',x,y2,'bo') -1

hold on; -1.5

plot(x,y3,'r--') -2
0 1 2 3 4 5 6 7

La commande hold on permet de continuer à tracer sur le même graphique,


sinon seul le dernier appel à la fonction plot est pris en compte.
24 / 42
Graphique
Combinaison de graphiques avec subplot :

subplot(2,2,1)
x = linspace(0,10);
y1 = sin(x);
plot(x,y1)
title('Subplot 1: sin(x)') 1
Subplot 1: sin(x)
1
Subplot 2: sin(2x)

0.5 0.5

subplot(2,2,2) 0 0

y2 = sin(2*x); -0.5 -0.5

plot(x,y2) -1 -1
0 5 10 0 5 10
title('Subplot 2: sin(2x)')
Subplot 3: sin(4x) Subplot 4: sin(8x)
1 1

0.5 0.5
subplot(2,2,3)
0 0
y3 = sin(4*x);
-0.5 -0.5
plot(x,y3)
-1 -1
title('Subplot 3: sin(4x)') 0 5 10 0 5 10

subplot(2,2,4)
y4 = sin(8*x);
plot(x,y4)
title('Subplot 4: sin(8x)') 25 / 42
Pré-allocations
Pour initialiser un vecteur (liste) de taille n avec des zéros en Python,
vous écrivez généralement :

malist = []
for i in range(n):
malist.append(0)

De manière équivalente en MATLAB

malist = 0 %optionnel...
for i=1:n
malist(i) = 0
end

Avec MATLAB
Créer des vecteurs de grande taille par ajout à la fin (append) est
très inefficace,
et compliqué à étendre à des dimensions supérieures.

26 / 42
Pré-allocations
Les commandes zeros et ones sont très utiles pour créer des
matrices.

A = zeros(20, 10)

produit une matrice de 20 lignes et 10 colonnes de 0.

A = 4 * ones(1, 10)

produit une vecteur de taille 10 de cellules initialisées à 4.

>>A = zeros(2)
A =
0 0
0 0

un seul paramètre produit une matrice carrée.


Obtenir les dimensions
A = zeros(3, 8, 4)
>>size(A)
[3 8 4] % length(A) renvoie 8 (plus grande dim.) !
27 / 42
Vectorisation

MATLAB est optimisé pour travailler avec matrices et des vecteurs.


MATLAB propose une syntaxe concise et proche de la notation
mathématique pour ces opérations.
Les opérations vectorielles/matricielles sont plus efficaces que
les boucles.

Le passage d’un code avec des boucles vers des opérations


vectorielles/matricielles s’appelle la vectorisation.

28 / 42
Vectorisation

La vectorisation est un élément clé pour écrire un code


MATLAB efficace

Comparons deux versions qui calculent la formule


suivante pour chaque élément de deux matrices de taille
m×n

z = x 2 sin y

Pas bien Bien

for i = 1: m
for j = 1: n
z(i,j) = x(i,j)^2*sin(y(i,j)); z = x .^2 .* sin (y)
end
end

Testons les performances de ces codes en pratique...


29 / 42
Vectorisation
Exemple complexe avec conditions
x < 0,


 5
x

0 ≤ x < 1,
f (x) =


 2−x 1 ≤ x ≤ 2,
3 x>2

function y=f1(x)
n=length(x);
for i=1:n
if x(i)<0
y(i)=5;
elseif x(i)<1
y(i)=x(i);
elseif x(i)<=2
y(i)=2-x(i);
else
y(i)=3;
endif
end

f2 = @(x) 5*(x<0)+ x.*(x>=0).*(x<1)+(2-x).*(x>=1).*(x<=2)+3*(x>2);


30 / 42
Optimisation
Opérations sur place
Cette ligne est une opération sur place (in-place) :
x = 4*x + 5;
Cette ligne ne l’est pas :
y = 4*x + 5;

Comment reconnaître ?
Le nom de la variable apparaît des deux côtés
Opération élément par élément

31 / 42
Optimisation
Opérations sur place

Que se passe-t-il en pratique ?

x = rand(6000);y = rand(6000);
% Sur place
x = sin(sqrt(3*x.^6+2*x+3));

% A emporter
z = sin(sqrt(3*x.^6+2*x+3));

32 / 42
Optimisation
Opérations sur place

Que se passe-t-il en pratique ?

x = rand(6000);y = rand(6000);
% Sur place
x = sin(sqrt(3*x.^6+2*x+3));

% A emporter
z = sin(sqrt(3*x.^6+2*x+3));

Compromis
A n’utiliser que lorsque vous manipuler de grandes matrices et que
vous avez des soucis de performances car peut nuire à la lisibilité du
code et au débogage.

32 / 42
Conclusion

Nous avons vu que MATLAB était un environnement complet dédié aux


méthodes numériques, optimisé pour le calcul matriciel, que sa
syntaxe simple et concise rend facile à exprimer. En contrepartie, il est
très permissif ce qui peut engendrer des erreurs silencieuses
difficilement détectables.

Résumé des bonnes pratiques en vrac


Privilégier la vectorisation
Pré-allouer les vecteurs utilisés autant que faire se peut,
l’allocation dynamique c’est mal !
Définir une fonction par fichier
Bien indenter son code

Économies
Il y a beaucoup de choses à faire avant d’acheter une machine plus
puissante !

33 / 42
Exercice 1

Soit le carré magique suivant (obtenu grâce à la fonction MATLAB


magic(3)) :
 
8 1 6
3 5 7
4 9 2
Nous cherchons un algorithme qui remplace toutes les valeurs
strictement supérieures à 4 dans cette matrice par leur négatif.
1 Écrire une version en MATLAB avec des boucles.
2 Écrire une version vectorisée en MATLAB (sans boucle).

34 / 42
Correction

carre = magic(1000);
a = carre;
tic
for i=1:size(a,1)
for j=1:size(a,2)
if a(i,j) > 4
a(i,j) = -a(i,j);
end
end
end
toc
b = carre;
tic
b(b>4) = -b(b>4); % version vectorisée
toc
isequal(a,b)

Il est possible mesurer le temps d’exécution en entourant le code des


commandes tic et toc.
35 / 42
Exercice 2

Évaluation naïve d’un polynôme


Soit un polynôme p(x) = an x n + an−1 x n−1 + · · · + a1 x + a0 , la
méthode naïve d’évaluation de p en un x donné consiste à calculer
chacun des termes de degrés allant de n à 0 puis à en faire la somme.

1 Évaluer p0 (x) = 2x 3 − 3x 2 + 5x − 7 pour x = 3


2 Écrire la version naïve en MATLAB de l’évaluation d’un polynôme
avec des boucles.
3 Quelle est la complexité pire-cas de la méthode naïve ?
4 Écrire la version naïve vectorisée en MATLAB.

36 / 42
Exercice 2

Schéma de Ruffini-Horner
La méthode de Ruffini-Horner propose une notation alternative du
polynôme, mathématiquement équivalente :
p(x) = ((((an x) + an−1 )x + · · · a1 )x) + a0 .

1 Vérifier la valeur de p0 (x) pour x = 3.


2 Écrire la version MATLAB du schéma de Ruffini-Horner (avec des
boucles).
3 Quelle est la complexité pire-cas du schéma de Ruffini-Horner ?
Quelle méthode est à privilégier ?

37 / 42
Correction

p = randi(10,10,1)';
x = randi(15,1,1);

tic
%version naive en O(n^2) (n(n+1)/2)
eval_naive = 0;
for i = 1:length(p)
l = 1;
for j = length(p)-i:-1:1
l = l * x;
end
eval_naive = eval_naive + p(i)*l;
end
toc

tic
%version naive vectorisée
n = length(p)-1:-1:0;
eval_vec = sum((x.^n).*p);
toc
38 / 42
Correction

tic
%Ruffini-Horner en O(n)
eval_horner = p(1);
for i=2:length(p)
eval_horner = eval_horner * x + p(i);
end
toc

tic
eval_octave = polyval(p,x);
toc

fonction polyval
La méthode polyval de MATLAB implémente le schéma de
Ruffini-Horner pour l’évaluation d’un polynôme.

39 / 42
Exercice 3

Soit a et b des matrices de nombres de même taille et c une matrice


de booléens, on cherche à calculer la matrice d suivant la condition
suivante :
(
aij si cij est vrai,
dij =
bij sinon.

1 Écrire une version avec boucle.


2 Écrire une version vectorisée.

40 / 42
Correction

n = 3;m = 4;
d = zeros(n,m);
a = randi([1 30],n,m)
b = randi([1 30],n,m)
c = randi([0 1], n,m)

if ~(numel(a) == numel(b) && size(a) == size(b))


error('size are not equal')
end
for i=1:size(a,1)
for j=1:size(a,2)
if c(i,j)
d(i,j) = a(i,j);
else
d(i,j) = b(i,j);
end
end
end
d
dvec = a .* c + b .* ~c
dvec == d
41 / 42
Exercice 4

Soit la formule
 d’approximation de  π de Leibniz :
1 1 1 1
π ≈ 4 × 1 − 3 + 5 − 7 · · · ± 2n+1

1 Proposer une fonction MATLAB en version vectorisée sans boucle


ni condition. Vous pouvez utiliser les fonctions MATLAB telles que
max, abs, sum, mod, etc.

42 / 42
Exercice 4

Soit la formule
 d’approximation de  π de Leibniz :
1 1 1 1
π ≈ 4 × 1 − 3 + 5 − 7 · · · ± 2n+1

1 Proposer une fonction MATLAB en version vectorisée sans boucle


ni condition. Vous pouvez utiliser les fonctions MATLAB telles que
max, abs, sum, mod, etc.

function [mypi] = approxpi(n)


i = 0:n-1;
mypi = 4 *sum(((-1).^mod(i,2)) .* (1./(2.*i + 1)));
%mypi = 4 *sum((-2.*(mod(i,2))+1) .* (1./(2.*i + 1)));

42 / 42

Vous aimerez peut-être aussi