Vous êtes sur la page 1sur 79

MILESI Alexandre, TC04

Cahier d’intégration

MT94 - Introduction aux mathématiques appliquées

Printemps 2017
Table des matières

1 Problèmes non linéaires 5


1.1 Différence avec les problèmes linéaires . . . . . . . . . . . . . . . . . . . . . . . . 5
1.2 Méthodes numériques . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 6
1.2.1 Dichotomie . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 6
1.2.2 Méthode du point fixe . . . . . . . . . . . . . . . . . . . . . . . . . . . . 7
1.2.3 Méthode de Newton . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 8
1.2.4 Méthode de la tangente . . . . . . . . . . . . . . . . . . . . . . . . . . . 9
1.3 Ordres de convergence . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 10
1.4 Différentiation numérique . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 12
1.4.1 Erreur de précision . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 12
1.4.2 Erreur de troncature . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 13
1.4.3 Erreur totale et h optimal . . . . . . . . . . . . . . . . . . . . . . . . . . 13
1.4.4 Validation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 14
1.5 Cinématique inverse . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 15

2 Fractales 17
2.1 Exemple : l’ensemble de Cantor . . . . . . . . . . . . . . . . . . . . . . . . . . . 17
2.2 Dimension . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 17
2.2.1 Dimension topologique . . . . . . . . . . . . . . . . . . . . . . . . . . . . 17
2.2.2 Dimension de Hausdorff . . . . . . . . . . . . . . . . . . . . . . . . . . . 18
2.3 Implémentation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 18
2.4 Triangle de Sierpiński . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 19
2.5 Tapis de Sierpiński . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 20
2.6 Arbre de Pythagore . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 21
2.7 Fougère de Barnsley . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 22
2.8 Ensemble de Mandelbrot . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 23
2.9 Ensemble de Julia . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 24

1
3 Equations différentielles ordinaires 27
3.1 Schéma numérique . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 28
3.2 Stabilité, consistance et ordre d’un schéma numérique . . . . . . . . . . . . . . . 29
3.2.1 Stabilité . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 29
3.2.2 Consistance . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 30
3.2.3 Ordre de convergence . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 30
3.3 Autres schémas numériques . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 30
3.3.1 Schéma du point milieu . . . . . . . . . . . . . . . . . . . . . . . . . . . 30
3.3.2 Schéma d’Euler-Cauchy . . . . . . . . . . . . . . . . . . . . . . . . . . . 30
3.3.3 Schéma de Runge-Kutta d’ordre 4 . . . . . . . . . . . . . . . . . . . . . . 31
3.4 Implémentation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 31
3.5 Applications . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 33
3.5.1 Pendule simple . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 33
3.5.2 Mécanique céleste . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 34
3.5.3 Attracteur étrange . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 36
3.5.4 Modèle proie-prédateur . . . . . . . . . . . . . . . . . . . . . . . . . . . . 37

4 Valeurs propres et applications 39


4.1 Décomposition en valeurs singulières (SVD) . . . . . . . . . . . . . . . . . . . . 39
4.1.1 Théorie . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 39
4.1.2 Application : Compression d’images . . . . . . . . . . . . . . . . . . . . . 40
4.2 Méthode des puissances . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 43
4.2.1 Théorie . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 43
4.2.2 Application : PageRank . . . . . . . . . . . . . . . . . . . . . . . . . . . 43

5 Moindres carrés et régression 50


5.1 Problème des moindres carrés linéaire . . . . . . . . . . . . . . . . . . . . . . . . 50
5.1.1 Théorie . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 50
5.1.2 Implémentation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 52
5.1.3 Restauration d’une image . . . . . . . . . . . . . . . . . . . . . . . . . . 55
5.2 Problème de régression non-linéaire . . . . . . . . . . . . . . . . . . . . . . . . . 57
5.3 Méthode du gradient . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 59

6 Séries de Fourier 62
6.1 Théorie . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 62

2
6.2 Applications . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 63
6.2.1 Périodisation d’une fonction . . . . . . . . . . . . . . . . . . . . . . . . . 63
6.2.2 Équation de la chaleur . . . . . . . . . . . . . . . . . . . . . . . . . . . . 67

A Problèmes non linéaires 71

B Fractales 72

3
Introduction

Ce cahier présente mon travail durant les différents chapitres de l’UV MT94. J’y décrit les
fondamentaux théoriques de chaque notion, puis les applications faites en TD, en plus de
mes recherches personnelles et travaux complémentaires. L’UV n’étant qu’une introduction
aux mathématiques appliquées, je ne suis pas forcément allé au fond des possibilités de
chaque application, même si j’aurais aimé avoir plus de temps pour le faire.
Bonne lecture !

4
Chapitre 1

Problèmes non linéaires

Les problèmes non linéaires peuvent parfois être difficiles ou long à résoudre analytique-
ment, comme par exemple la résolution de polynômes de degré 4 ou plus, ou la détermi-
nation des angles d’un pendule double en connaissant sa position. Il est alors plus simple
d’approcher les solutions numériquement.

1.1 Différence avec les problèmes linéaires


Pour bien comprendre la différence entre un problème linéaire et un problème non linéaire,
prenons un cas linéaire : un système de n équations linéaires à n inconnues.

a11 x1

 + · · · + a1n xn = b1
..

. (1.1)


a
n1 x1 + · · · + ann xn = b1

.
Ce système peut être écrit sous la forme matricielle :

Ax = b , (1.2)
avec      
a11 . . . a1n x1 b1
 . .. 
A =  ..  , x =  ..  , b =  ..  .
   

.   .  .
an1 . . . ann xn bn

Si det A 6= 0, A est inversible et on a la solution unique x = A−1 b. On résout ces problèmes


grâce aux méthodes de Cramer et de Gauss.
Or, dans le cas non linéaire, il est plus difficile de résoudre l’équation matricielle. On se
penche donc sur des méthodes d’approximation numérique.

5
1.2 Méthodes numériques
Pour résoudre un système non linéaire f (x) = Ax + B numériquement, on va chercher
à construire une suite (xn )n≥0 dont la limite x∗ vérifie f (x∗ ) = ~0. On itère ensuite jusqu’à
atteindre une certaine précision ou jusqu’à atteindre un nombre d’itérations maximal.

1.2.1 Dichotomie
La dichotomie est une méthode qui part d’un intervalle quelconque contenant la solution
x∗ . À chaque itération, on le sépare en deux, en gardant l’intervalle contenant toujours x∗ .
Cette méthode ne nécessite pas de connaître la dérivée de la fonction, il suffit que celle-ci
soit continue.
Prenons le cas où n = 1 pour simplifier, même si la dichotomie fonctionne pour tout n.
Soient f : R → R continue et [a, b] tel que f (a)f (b) < 0. D’après le théorème des valeurs
intermédiaires, il existe une solution dans [a, b]. On définit les suites (an )n≥0 et (bn )n≥0 avec
a0 = a, b0 = b. La suite (xn )n≥0 vérifie

an + b n
xn = .
2
On définit an+1 et bn+1 par :

Si f (an )f (xn ) > 0 alors


an+1 ← xn
Sinon
bn+1 ← xn
FinSi

Nombre d’itérations

On cherche le nombre d’itérations n tel que |xn − x∗ | < ε. À chaque itération, la longueur de
l’intervalle est divisée par deux. On a :

b−a
b n − an = ,
2n

b n − an
|xn − x∗ | ≤ ,
2
et donc,

b−a
|xn − x∗ | ≤ .
2n+1
On pose alors

b−a
< ε,
2n+1

6
ce qui nous donne : !
b−a
n ≥ log2 .

Convergence

Par construction,  n
1
(bn − an ) = (b0 − a0 ) ,
2
or,
1
|xn − x∗ | ≤ (bn − an )
2
 n+1
1
|xn − x∗ | ≤ (b0 − a0 ) ,
2
et donc on a bien
lim |xn − x∗ | = 0 .
n→inf

Programme

function x=dichotomie(a, b, fonc, prec, N)


x = zeros(N, 1)
for k=1:N
x(k) = (a + b)/2

if(abs(fonc(x(k)))<prec) then
break
end

if(fonc(x(k))*fonc(a) > 0) then


a = x(k)
else
b = x(k)
end
end
x = x(1:k)
endfunction
Code Scilab 1.1 – Méthode de la dichotomie

1.2.2 Méthode du point fixe


Soit f dérivable, on cherche une fonction g : R → R qui admet un point fixe, c’est à dire :
f (x∗ ) = 0 ⇐⇒ g(x∗ ) = x∗ .

Si g est dérivable et si on admet on point fixe x∗ tel que x∗ = g(x∗ ) et |g 0 (x∗ )| < 1, alors il
existe un intervalle [a, b] tel que x∗ ∈ [a, b] et la suite (xn ) définie par :

x
0 ∈ [a, b]
(1.3)
xn+1 = g(xn ) , n ≥ 0

7
converge vers x∗ .

Convergence

Si 0 < |g 0 (x∗ )| < 1 alors on a

|xn+1 − x∗ |
< k,0 < k < 1.
|xn − x∗ |

Par récurrence, on trouve que

|xn+1 − x∗ | < k n |x0 − x∗ | ,

et donc
lim |xn − x∗ | = 0 .
n→inf

Il faut préciser que si |g 0 (x∗ )| > 1, la méthode du point fixe ne converge pas. Si |g 0 (x∗ )| = 1,
la convergence est incertaine.

Programme

function x=ptfixe(x0, gFonc, fonc, prec, N)


x = zeros(N, 1)
x(1)=x0
for k=2:N
x(k) = gFonc(x(k-1))

if(abs(fonc(x(k)))<prec) then
break
end
end
x = x(1:k)
endfunction
Code Scilab 1.2 – Méthode du point fixe

1.2.3 Méthode de Newton


Si f est deux fois continûment dérivable, la méthode de Newton consiste à appliquer la
méthode du point fixe avec g(x) = x − ff0(x)
(x)
. Ainsi, xn+1 est le point d’intersection entre l’axe
des abscisses et la tangente de la courbe de f en xn .

Convergence

Si f 0 (x∗ ) 6= 0, on a
0 f 0 (x)2 − f (x)f 00 (x)
g (x) = 1 − ,
f 0 (x)2

8
d’où
f 0 (x∗ )2
g 0 (x∗ ) = 1 − = 0.
f 0 (x∗ )2
On a |g 0 (x∗ )| < 1 donc la suite (xn ) :

x
0 = x0
f (xn ) (1.4)
xn+1 = xn − f 0 (xn )

converge vers x∗ .

Programme

function x=newton(x0, dfonc, fonc, prec, N)


x = zeros(N, 1)
x(1)=x0
for k=2:N
x(k) = x(k-1) - fonc(x(k-1))/dfonc(x(k-1))

if(abs(fonc(x(k)))<prec) then
break
end
end
x = x(1:k)
endfunction
Code Scilab 1.3 – Méthode de Newton

1.2.4 Méthode de la tangente


Lorsque la dérivée de f est trop difficile à calculer pour appliquer la méthode de Newton,
on peut l’approcher par
f (xk ) − f (xk−1 )
f 0 (xk ) = .
xk − xk−1
Ce qui nous donne la suite

x
0 = x0
−xn−1 . (1.5)
xn+1 = xn − f (xn ) f (xxnn)−f (xn−1 )

9
Programme

function x=secante(a,b,fonc, prec, N)


x = zeros(N, 1)
x(1)=a
x(2)=b
for k=3:N
if(abs(fonc(x(k-1)))<prec | fonc(x(k-1))-fonc(x(k-2)) == 0) then
break
end
dX = x(k-1)-x(k-2)
dF = fonc(x(k-1))-fonc(x(k-2))
x(k) = x(k-1)-fonc(x(k-1))*dX/dF

end
x = x(1:k-2)
endfunction
Code Scilab 1.4 – Méthode de la tangente

1.3 Ordres de convergence


Pour savoir si une méthode converge plus ou moins vite vers la solution par rapport à une
autre, on peut calculer leur ordre de convergence α. On le définit par :

|xk+1 − x∗ |
lim =q>0 (1.6)
k→+∞ |xk − x∗ |α

On peut comparer les différentes méthodes expérimentalement et approcher leur ordre de


convergence grâce à la régression linéaire. En effet, on a

|xk+1 − x∗ | ≈ q|xk − x∗ |α ,

et donc
log |xk+1 − x∗ | ≈ α log |xk − x∗ | + log q . (1.7)

On peut donc, pour chaque méthode, récupérer la liste des xk et tracer log |xk+1 − x∗ | en
fonction de log |xk − x∗ |. L’ordre de convergence α sera alors la pente de la courbe, que l’on
peut estimer grâce à la macro reglin.
2
√ une fonction quelconque, par exemple f (x) = x − 2. La solution recherchée est
On choisit

x = 2. Cette solution est comprise dans [0, 2], qui est l’intervalle qu’on utilisera pour la
dichotomie.

10
function y =f(x)
y = x^2 - 2
endfunction

function y =Jf(x)
y = 2*x
endfunction

function y=g(x)
y = (x+2)/(x+1)
endfunction
Code Scilab 1.5 – Définition des fonctions

Nmax = 100
prec = 10D-13
a = 0
b = 2

sol = sqrt(2)
Code Scilab 1.6 – Définition des constantes

On peut maintenant tracer les courbes et calculer les ordres de convergence (programme
en annexe A.1). On obtient la figure 1.1. On remarque que pour la dichotomie et pour la
méthode du point fixe, on a une convergence linéaire, alors que pour la méthode de Newton,
la convergence est quadratique, et donc plus rapide. L’ordre de convergence

de la méthode
1+ 5
de la sécante correspond approximativement au nombre d’or Ψ = 2 . On remarque aussi
que la convergence de la dichotomie n’est pas monotone.

Figure 1.1 – Courbes et ordres de convergence des 4 méthodes

11
1.4 Différentiation numérique
En découvrant la macro fsolve, j’ai appris qu’il n’était pas obligatoire (seulement fortement
recommandé) de fournir la fonction dérivée (ou matrice Jacobienne). Étant donné que la mé-
thode de Newton repose sur l’utilisation de la dérivée, fsolve doit l’approximer. Je me suis
donc demandé comment calculer une dérivée numériquement. Après avoir fait quelques
recherches[2][3][4] , j’ai remarqué que cela soulevait des problèmes que je ne soupçonnait pas.
Tout d’abord, une définition de la dérivée est la suivante :
f (x + h) − f (x)
f 0 (x) = lim , (1.8)
h→0 h
qui converge à l’ordre 1. On peut trouver une autre définition qui converge à l’ordre 2, et
donc plus rapidement :
f (x + h) − f (x − h)
f 0 (x) = lim , (1.9)
h→0 2h
mais cela nous oblige à appeler deux fois la fonction f , alors que dans l’équation (1.8), si
on utilise la méthode de Newton, on a déjà f (x) à notre disposition, et donc un seul appel
supplémentaire à f est nécessaire.
L’équation (1.8) n’est valable que pour un h infiniment petit, impossible donc de l’appli-
quer en calcul numérique ! Pour se débarasser de la limite, on utilise le développement de
Taylor :
f (x + h) = f (x) + hf 0 (x) + hE(h) , (1.10)
avec
lim E(h) = 0 .
h→0

On obtient donc
f (x + h) − f (x)
f 0 (x) = − E(h) , (1.11)
h
où E(h) est l’erreur qui tend vers 0 plus h est petit. Je me suis alors dit qu’il suffisait de
choisir un h extrêmement petit (peut-être ε machine), et le tour est joué. Quelle naïveté !
En effet, dans l’équation (1.11), on divise la différence par h. Donc plus h est petit, plus on
multiplie cette différence par un grand nombre, ce qui a pour effet d’amplifier grandement
l’erreur d’arrondissement qui peut être faite par Scilab ! Par exemple, si h est de l’ordre de
ε, toute erreur de la 16ème décimale sera amplifiée en unités. Il ne faut donc pas choisir un h
trop petit. Mais si on le choisit trop grand, l’erreur de troncature E devient importante. Il faut
donc faire un compromis entre exactitude et précision. Mais comment choisir un h optimal ?

1.4.1 Erreur de précision


Penchons-nous d’abord sur l’erreur d’arrondissement faite par Scilab quand on calcule la
dérivée (1.11). L’erreur absolue d’évaluation d’une fonction en un point est de l’ordre de
ε|f (x)|. L’erreur sur le quotient de l’équation (1.11) peut donc être estimée par

ε|f (x + h)| + ε|f (x)|


Ep ≈ .
h
On pose
Lf = max(|f (x + h)|, |f (x)|) ,

12
on a donc
Lf
Ep ≤ 2ε . (1.12)
h
On voit bien que plus h est grand, plus l’erreur d’arrondi est petite.

1.4.2 Erreur de troncature


Attaquons maintenant l’erreur de troncature lors du calcul de la dérivée. On peut préciser
l’erreur de l’équation (1.11) avec le développement de Taylor-Lagrange si on suppose f 2
fois continûment dérivable :
h2 00
f (x + h) = f (x) + hf 0 (x) + f (c) , c ∈ [x, x + h] . (1.13)
2

L’erreur de troncature est donc


h 00
Et = |f (c)| .
2
Soit
Mf = sup |f 00 (x)| ,
x∈[x,x+f ]

alors on peut majorer l’erreur de troncature :

hMf
Et ≤ . (1.14)
2
On vérifie que plus h est petit, plus l’erreur de troncature est petite.

1.4.3 Erreur totale et h optimal


On peut maintenant majorer, à partir des erreurs (1.12) et (1.14), l’erreur totale E = Et + Ep .
On a donc :
hMf Lf
E≤ + 2ε ,
2 h
avec
^
f (x + h) − fg
(x)

0

E= − f (h) ,
h
où fg
(x) est la valeur numérique de f (x). On cherche alors à minimiser E(h).

Mf 2εLf
E 0 (h) = − 2 .
2 h

Si on appelle ĥ le h optimal, s
0 4εLf
E (ĥ) = 0 ⇔ ĥ = .
Mf
En pratique, on ne peut pas forcément calculer Lf et Mf . Une bonne approximation de ĥ est
alors s
Lf √ √
ĥ ≈ ε ≈ |x| ε . (1.15)
Mf

13
1.4.4 Validation
Pour vérifier que cette démarche soit valide, j’ai écrit un petit programme Scilab qui permet
de comparer mes résultats avec ceux de la méthode numderivative, qui est une fonction
dédiée à l’approximation de dérivées. Avec une fonction f (x) = ln(x) + x5 et une valeur de
x = 5.2 choisies arbitrairement, on obtient les erreurs relatives suivantes :
Algorithme perso

0.0000000279301

Numderivative

0.0000000000739
Code Scilab 1.7 – Résultats du comparatif

function y = f(x)
y = log(x) + x^5 //arbitraire
endfunction

function out = df(x)


out = 1/x + 5*x^4
endfunction

x = 5.2; //arbitraire

h = sqrt(%eps)*x;

valid = df(x);
cust = (f(x+h) - f(x))/h;
num = numderivative(f, x);

disp(abs((valid-cust)/valid), "Algorithme␣perso")
disp(abs((valid-num)/valid), "Numderivative")
Code Scilab 1.8 – Comparatif entre mon algorithme et numderivative

On voit que mon algorithme a une précision de l’ordre de 10−7 , ce qui n’est pas mauvais,
mais numderivative atteint une précision de 10−10 . J’en conclus que numderivative prend
en compte d’autres paramètres afin d’affiner le résultat.
De plus, dans cet exemple arbitraire, quand on divise h par 4, l’erreur relative baisse encore.
On en déduit que dans ce cas, c’est l’erreur de troncature qui était la plus importante. Quand
on divise h par 5, l’erreur remonte, c’est donc l’erreur d’arrondi qui prend le relais.

14
1.5 Cinématique inverse
Avec cet exercice, on est confronté à un problème concret : on cherche à atteindre un certain
point dans l’espace grâce à un bras à deux segments, pouvant bouger indépendamment
l’un de l’autre. Cet exercice simple reflète ce qui peut être développé dans la robotique et
l’automatisation.
Résoudre un problème de cinématique inverse revient à résoudre un système d’équations
non-linéaires. C’est ici qu’intervient la méthode de Newton et la macro fsolve.
Commençons d’abord par définir la fonction à annuler. Grâce à un peu de trigonométrie, on
déduit que le système à résoudre est de la forme
(
xc = l1 cos θ1 + l2 cos(θ1 + θ2 )
,
yc = l1 sin θ1 + l2 sin(θ1 + θ2 )

où xc , yc sont les coordonnées à atteindre, l1 , l2 sont les longueurs respectives des segments
du bras, θ1 est l’angle entre les abscisses et le premier segment, et θ2 est l’angle entre le
deuxième segment et le premier.
On écrit donc dans Scilab la fonction :
function y = f(theta, long, cible)
y = [cos(theta(1)) * long(1) + cos(sum(theta)) * long(2) - cible(1);
sin(theta(1)) * long(1) + sin(sum(theta)) * long(2) - cible(2)]
endfunction
Code Scilab 1.9 – Fonction f à annuler

On pourrait s’arrêter là et appeler la fonction fsolve avec comme paramètres l’état de départ
et la fonction f, mais pour améliorer le temps de résolution il est préférable de calculer la
matrice Jacobienne
" #
−l1 sin θ1 − l2 sin(θ1 + θ2 ) −l2 sin(θ1 + θ2 )
Jf = ,
l1 cos θ1 + l2 cos(θ1 + θ2 ) l2 cos(θ1 + θ2 )

ce qui, intégré à Scilab, donne :


function out = Jf(theta, long)
out = [-long(1) * sin(theta(1)) - long(2) * sin(sum(theta)),...
-long(2)*sin(sum(theta));
long(1)*cos(theta(1)) + long(2)*cos(sum(theta)),...
long(2)*cos(sum(theta))]
endfunction
Code Scilab 1.10 – Matrice Jacobienne Jf

À ce point, on peut résoudre θ1 et θ2 pour tout point de coordonnées c, accessible par le bras,
c’est-à-dire l1 − l2 ≤ |c| ≤ l1 + l2 . Par exemple, on peut résoudre pour des points appartenant
à une courbe paramétrique, le bras se déplace alors petit à petit et suit la courbe. Dans ce cas,
si la courbe est continue, les positions successives du bras sont très proches. On peut donc,
à chaque itération, choisir comme vecteur de départ la dernière configuration prise par le
bras. Si on ne le fait pas, le bras risque d’être instable puisque la résolution a deux solutions
symétriques, et choisir un point de départ proche de la solution permet de toujours rester
dans la même configuration.

15
Figure 1.2 – Cinématique inverse avec la courbe papillon

On a, en TP, expérimenté avec un simple cercle. Je me suis ensuite penché sur une figure
plus esthétique, la courbe papillon [1] . On a donc la boucle principale suivante :
l = [4.5, 4.5] //longueur des bras
PAS = 0.05 //precision de l'animation
TFIN = 30 //longueur de l'animation
theta0 = zeros(2, 1) //pour la premiere iteration

//pour stocker la courbe au fur et a mesure


points = zeros(TFIN/PAS, 2)

k = 0
for t=0:PAS:TFIN
k = k+1
//equation de la courbe papillon
cible = [4 + sin(t) * (%e^cos(t) - 2*cos(4*t) - sin(t/12)^5),...
2 + cos(t) * (%e^cos(t) - 2*cos(4*t) - sin(t/12)^5)]

theta = fsolve(theta0, list(f, l, cible), list(Jf, l));


points(k,:) = cible
dessine_bras(theta, l, points(1:k,:))
//le vecteur de depart de la prochaine iteration
theta0 = theta;
end
Code Scilab 1.11 – Boucle principale de cinématique inverse

Ce qui nous donne l’animation 1.2. Il est possible, en changeant juste la définition de cible,
de suivre n’importe quelle courbe, continue ou non, ou même le curseur de la souris.

16
Chapitre 2

Fractales

Attaquons maintenant une partie passionnante des mathématiques, les fractales. Les frac-
tales sont des figures qui conservent leur structure, peu importe à quelle échelle on l’ob-
serve, à la manière de poupées russes infinies. Elles sont obtenues grâce à un ensemble de
transformations contractantes (ou lipschitziennes), qu’on applique à une certaine figure une
infinité de fois. En TP, j’ai pu découvrir comment implémenter ces fractales, en commençant
par celles plus simples.

2.1 Exemple : l’ensemble de Cantor


L’ensemble de Cantor est une fractale qui s’obtient facilement. On part d’un segment C (0) =
[0, 1]. On le sépare en 3 parties égales et on oublie celui du milieu. On obtient donc deux
segments, qui forment l’ensemble C 1 = C10 C30 . On répète de nouveau l’opération sur tous
S

les segments de ce nouvel ensemble. A l’infini, on a :



C (∞) = Ck .
\

k=0

Prouvons que |C (∞) | = 0. Par récurrence, on a :


 2 k
|C (k) | = ,
3
et donc
lim |C (k) | = 0 .
k→∞

2.2 Dimension
Comment déterminer la dimension d’une fractale ? Il y a plusieurs façons de le faire.

2.2.1 Dimension topologique


Si à chaque étape de la création de la fractale, on partage l’ensemble précédent en N parties
égales homothétiques de rapport r (0 < r < 1), on a alors la dimension topologique d qui
vérifie :

17
1
N= (2.1)
rd
Par exemple pour l’ensemble de Cantor, on double le nombre de segments à chaque étape,
donc N = 2, et chaque segment mesure r = 13 de la longueur du segment père. On a donc
2 = 3d , donc la dimension topologique de l’ensemble de Cantor est d = log 2
log 3
∈]0, 1[. On
remarque que la dimension n’est pas entière, ce qui est typique des fractales.

2.2.2 Dimension de Hausdorff


La dimension de Hausdorff de la fractale K ⊂ R2 est définie par :

log N ()
d = lim , (2.2)
→0 log 1
avec N () le nombre de carrés ou disques de longueur  recouvrant K.

2.3 Implémentation
Pour visualiser des fractales avec Scilab, deux méthodes peuvent être utilisées : la récursi-
vité, ou la méthode itérative.
La méthode récursive consiste à définir une fonction qui prend en paramètre une figure.
Dans cette fonction, on calcule pour chaque transformation de la fractale une nouvelle fi-
gure. Pour chacune de ces sous-figures, on appelle de nouveau cette même fonction. De
plus, pour éviter une récursivité infinie, on gère le niveau de récursivité pour arrêter la
branche lorsqu’elle atteint un certain niveau. Comme on va le voir, cette méthode permet
d’obtenir des figures très propres pour des niveaux de récursivité faibles, mais peut prendre
énormément de temps si on cherche à visualiser des niveaux plus élevés.
La méthode du système de fonctions itérées permet de résoudre ce problème. Si une fractale
est définie par un ensemble de N fonctions Ti , on définit une fonction T telle que
N
[
T (F ) = Ti (A) .
i=1

Barnsley a démontré qu’on peut approximer la fractale, ou attracteur, en partant d’un en-
lim T n (F0 ) . par composition. Cela permet d’obtenir une
semble compact F0 et en calculant n→∞
visualisation d’une fractale bien plus rapidement qu’avec la récursivité, il nous suffit juste
de connaître l’ensemble des transformations de chaque fractale.
Dans la suite, l’ensemble de départ sera un point. On itère n fois, en choisissant à chaque
itération une fonction au hasard pour générer un point à partir du dernier point généré. On
obtient alors un nuage de points qui converge vers la fractale finale.

18
2.4 Triangle de Sierpiński

Figure 2.1 – Triangle de Sierpiński en récursif

Figure 2.2 – Triangle de Sierpiński en itératif

Prenons un triangle équilatéral quelconque. On peut le diviser en quatre triangles équila-


téraux de tailles égales. En ignorant celui du centre, on se retrouve avec trois triangles. On
peut, pour chacun d’entre eux, le diviser en quatre autres triangles équilatéraux, et ignorer
ceux du centre. En répétant cette opération pour tous les triangles à l’infini, on obtient le
fameux Triangle de Sierpiński.
Pour tout point W , le triangle de Sierpiński peut être défini à l’aide de 3 transformations :

f1 (W ) = AW


f2 (W ) = AW + B1 ,



f3 (W ) = AW + B2
où " # " # " #
0.5 0 0.5 0.25
A= , B1 = et B2 = √3 .
0 0.5 0 4

On peut voir ces fonctions comme les transformations qu’on applique à un triangle pour ob-
tenir les 3 sous-triangles. La matrice A permet de redimensionner le triangle, et les matrices
Bi permettent de positionner les sous-triangles aux extrémités du grand triangle.
J’ai donc écrit un programme récursif (B.1) et un autre itératif (B.3). En récursif avec 7 ni-
veaux, on obtient la figure 2.1. En itératif avec 300 000 itérations, on obtient la figure 2.2

19
2.5 Tapis de Sierpiński

Figure 2.3 – Tapis de Sierpiński en récursif

Figure 2.4 – Tapis de Sierpiński en itératif

Similairement au Triangle de Sierpiński, le Tapis de Sierpiński est construit à partir d’un carré,
qu’on divise en neuf carrés identiques. On ignore celui du milieu, et on répète l’opération
pour les huit autres carrés.
Le tapis de Sierpiński est lui défini par 8 fonctions :

fi (W ) = AW + Bi , ∀i ∈ {0, 1, 2, 3, 5, 6, 7, 8} ,
avec  j k 
" # i
1/3 0  3 
A= et Bi =  ,
0 1/3 
i mod 3

3

Les programmes sont similaires aux précédents. En récursif avec 5 niveaux, la figure 2.3 est
générée (code en annexe B.2). En itératif avec 400 000 itération, on obtient la figure 2.4 (code
en annexe B.4).

20
2.6 Arbre de Pythagore

Figure 2.5 – Arbre de Pythagore en récursif

Figure 2.6 – Arbre de Pythagore en itératif

L’Arbre de Pythagore consiste à partir d’un carré, de le transformer en deux carrés plus petits,
puis de déplacer ces deux carrés en haut du grand, de façon à créer un triangle rectangle
entre les trois carrés.
On peut définir une généralisation de l’arbre avec un angle a quelconque avec les transfor-
mations suivantes : 
f (W ) = A W + B
1 1 1
,
f2 (W ) = A2 W + B2

avec " #
cos(a)2 −cos(a) ∗ sin(a)
A1 = ,
cos(a) ∗ sin(a) cos(a)2
" #
sin(a)2 cos(a) ∗ sin(a)
A2 = ,
−cos(a) ∗ sin(a) sin(a)2
" #
0
B1 =
1
" #
cos(a)2
et B2 = .
1 + cos(a) ∗ sin(a)

En reprenant la structure des programmes précédents. On a en récursif la figure 2.5 (cliquer


dessus pour voir une animation avec a qui varie), et en itératif la figure 2.6 (programmes en
annexe B.5 et B.6).

21
2.7 Fougère de Barnsley

Figure 2.7 – Fougère de Barnsley en itératif

Jusque là, avec la méthode par itérations, les probabilités de choisir les différentes transfor-
mations étaient uniformes. La Fougère de Barnsley repose quant à elle sur des probabilités
différentes pour choisir les transformations. Ces transformations sont au nombre de quatre :



 f1 (W ) = A1 W + B1

f (W )

= A2 W + B2
2




f3 (W ) = A3 W + B3


f4 (W ) = A4 W + B4

avec
" # " # " # " #
0.85 0.04 0.2 −0.26 −0.15 0.28 0 0
A1 = , A2 = , A3 = , A4 = ,
−0.04 0.85 0.23 0.22 0.26 0.24 0 0.16
" # " # " #
0 0 0
B1 = B2 = , B3 = et B4 = .
1.6 0.44 0

On leur attribue respectivement les probabilités :

p1 = 0.85 , p2 = p3 = 0.07 , p4 = 0.01 .

Le programme disponible en annexe B.7 nous donne la figure 2.7.

22
2.8 Ensemble de Mandelbrot

Figure 2.8 – Représentation de l’ensemble de Mandelbrot

Soit la suite de nombres complexes suivantes :



z
0 =0
. (2.3)
zn+1 = zn2 + c

L’ensemble de Mandelbrot contient tous les complexes c tels que (zn ) converge. On peut
représenter la fractale résultant de cet ensemble en visualisant les c sur un plan. Il suffit
de définir un ensemble de complexes C, et de tester la convergence de la suite pour chaque
complexe, puis de les afficher avec une couleur différente en fonction de la vitesse de conver-
gence.
x = linspace(-1.5, 1, 500)
y = linspace(-1.5, 1, 500)

[X, Y] = meshgrid(x,y)
C = X+%i*Y

Z = zeros(length(x),length(y));
A = zeros(length(x), length(y))
Nbmax = 500;

//limite de divergence
Rc = max(abs(C), 2)
for i=1:Nbmax
Z=Z.^2+C
conver=abs(Z)<Rc

//on ajoute 1 pour chaque c qui converge encore


A(conver) = A(conver)+1
end

set(gca(), "isoview", "on")


set(gcf(), "color_map", jetcolormap(Nbmax))
grayplot(x, y, A)
Code Scilab 2.1 – Représentation de l’ensemble de Mandelbrot

23
On obtient la figure 2.8. La frontière entre la convergence et la divergence est infiniment
complexe, ce qui fait de cet ensemble une fractale.
L’ensemble rouge est l’ensemble des points pour lesquels la suite converge, on l’appelle
bassin attracteur.

2.9 Ensemble de Julia


L’ensemble de Julia est similaire à celui de Mandelbrot. En reprenant la même suite (2.3), on
fixe cette fois c, et on fait varier z0 . On affiche ensuite de manière similaires les complexes z0
pour lesquels la suite converge. L’ensemble de Julia représente la frontière entre les bassins
d’attraction et de répulsion.
Le choix de c est crucial, la figure obtenue dépend de c. Il est préférable de choisir des
nombres qui sont dans l’ensemble de Mandelbrot, car ceux-ci génèrent un ensemble connexe,
et donc une figure plus consistante, au lieu de points éparpillés.
x = linspace(-0.5, 0.5, 1000)
y = linspace(-0.5, 0.5, 1000)

[X, Y] = meshgrid(x,y)
Z = X+%i*Y

c = 0.32+%i*0.043

A = zeros(length(x), length(y))
Nbmax = 500;
Rc = max(abs(c), 2)

for i=1:Nbmax
Z=Z.^2+c
conver=abs(Z)<Rc
A(conver) = A(conver)+1

end

set(gca(), "isoview", "on")


set(gcf(), "color_map", jetcolormap(Nbmax))
grayplot(x, y, A)
Code Scilab 2.2 – Représentation de l’ensemble de Julia

En choisissant quelques c intéressants, on obtient les figures suivantes.

24
Figure 2.9 – Ensemble de Julia pour c = 0.32 + 0.043i

Figure 2.10 – Ensemble de Julia pour c = −0.162 + 1.04i

Figure 2.11 – Ensemble de Julia pour c = 0.285 + 0.013i

25
(xn )3 −1
Figure 2.12 – Figure bonus pour xn+1 = 3(xn )2

26
Chapitre 3

Equations différentielles ordinaires

On cherche à résoudre des équations différentielles numériquement, comment procéder ?


Soient :

t ∈ I = [t0 , t0 + T ], T > 0
f : I × Rm −→ Rm
.
(t, y) −→ f (t, y)
On s’intéresse à la résolution de problèmes de Cauchy sous la forme :

y 0 = f (t, y(t))
y(t0 )
(3.1)
= y0

Pourquoi l’espace Rm ? Prenons un exemple :



00
y

 + w2 y =0
y(0) =a (3.2)

 0

y (0) =b

On peut se ramener à un système différentiel d’ordre 1 en posant Y~ ∈ R2 tel que


!
y
Y~ = 1 ,
y2

où 
y 0 = y2
1
y 0 = −w2 y1
2
! !
y (0) a
Y~ (0) = 1 =
y2 (0) b

L’équation 3.2 est équivalente à :



0
Y1



=F (t, Y )
 
a ,t ∈ I (3.3)

Y (0) = 

 b

27
avec
F : I × R2 −→ R2 !
y2 .
(t, Y ) −→
−w2 y1

Dans le cas général, on a :







y (m) = h(t, y, y 0 , . . . , y (m−1) )




y(0) = a0

y 0 (0) = a1 (3.4)

.. ..
. .






y (m−1) (0)

= am

Ce qui nous ramène au système


 
y1
y2 = y10
 
a0
 
 
..  . 
 
Y =  .. 
, Y (0) =  (3.5)
 

 . 


0

 ym−1 = ym−2 
 am−1
ym = f (t, y1 , y2 , . . . , ym−1
et  
 y2
Y 0 = F (t, Y )
 .. 

, F (t, Y ) = 

 .
Y (0) = (a0 , . . . , am−1 )> 
 ym


f (t, y1 , . . . , ym−1 )

3.1 Schéma numérique


On crée une subdivision de [t0 , t0 + T ] : σ = t0 , . . . , tN , tN = t0 + T . Le pas de la subdivision
est h = max |ti+1 − ti |. Lorsque la subdivision est uniforme, on a hi = ti+1 − ti = C, ∀i.
0≤i≤N −1

On approche ensuite y au point ti par zi où



z
i+1 = zi + hΦ(ti , zi , hi )
(3.6)
z0 = y0

En utilisant le développement de Taylor, on peut en déduire le schéma d’Euler (subdivision


uniforme) :

zi+1

 = zi + hΦ(ti , zi , h)
z0 = y0 (3.7)



Φ(t, z, h) = f (t, z)

28
On peut aussi déduire ce schéma sans avoir recours à Taylor :
Z ti+1
y(ti+1 ) = y(ti ) + y 0 (t) dt
ti
Z ti+1
y(ti+1 ) = y(ti ) + f (t, y(t)) dt (3.8)
ti

On approche l’intégrale inconnue par l’aire du rectangle gauche :

y(ti+1 ) = y(ti ) + hf (ti , y(ti )) ,


et on retrouve le schéma explicite d’Euler.

3.2 Stabilité, consistance et ordre d’un schéma numé-


rique

3.2.1 Stabilité
La stabilité d’un schéma permet de savoir si une petite erreur pendant une étape se propage
et influence fortement les résultats suivants ou non.
Soient les suites (ui ) et (vi ) telles que :

u
i+1 = u1 + hΦ(ti , ui , h)
u0 donné
et 
v
i+1 = v1 + hΦ(ti , ui , h) + i
v0 donné

Le schéma est dit stable si


N
X
max |ui − vi | ≤ C(|u0 − v0 | + |i |)
i=1,...,N
i=1

avec C une constante.


On peut montrer que le schéma est stable si et seulement si

∃K > 0, ||Φ(t, y, h) − Φ(t, z, h)|| ≤ K||y − z|| .

Par exemple, le schéma d’Euler est stable si f est K-lipschitzienne par rapport à sa deuxième
variable :
Φ(t, y, h) = f (t, y)
donc
||Φ(t, y, h) − Φ(t, z, h)|| = ||f (t, y) − f (t, z|| .
.

29
3.2.2 Consistance
On dit que le schéma est consistant si

X
(y) = ||y(ti+1 ) − y(ti ) − Φ(ti , y(ti ), h|| −−→ 0 ,
h→0
ou, de manière équivalente :
Φ(t, y, 0) = f (t, y) .

Le schéma d’Euler est consistant car on a :


Φ(t, y, h) = f (t, y) .

3.2.3 Ordre de convergence


Le schéma numérique est d’ordre p si :
∃C > 0, max |y(ti ) − zi | ≤ Chp
i=1,...,N

On peut prouver que le schéma d’Euler est d’ordre 1.

3.3 Autres schémas numériques

3.3.1 Schéma du point milieu


En approchant l’intégrale de l’équation 3.8 par le rectangle du point milieu, on obtient :
h h
Φ(ti , zi , h) = f (ti + , zi + f (ti , zi )) ,
2 2
d’où le schéma : 


 k1 = f (ti , zi )
= zi + h2 k1

k

2
. (3.9)




zi+1 = zi + hf (ti + h2 , k2 )


z0 = y0

Ce schéma est stable, consistant et d’ordre 2.

3.3.2 Schéma d’Euler-Cauchy


Si on choisit d’approcher l’intégrale de l’équation 3.8 par l’aire du trapèze, on obtient le
schéma d’Euler-Cauchy :



 k1 = f (ti , zi )

k = f (ti + h, zi + hk1 )

2
(3.10)




zi = zi + h2 (k1 + k2 )


z0 = y0

Ce schéma est stable, consistant et d’ordre 2.

30
3.3.3 Schéma de Runge-Kutta d’ordre 4
Le schéma de Runge-Kutta classique est d’ordre 4, stable et consistant :



 k1 = f (ti , zi )

k2 = f (ti + h2 , zi + h2 k1





= f (ti + h2 , zi + h2 k2 )

k

3
(3.11)




k4 = f (ti + h, zi + hk3 )
= zi + 16 (k1 + 2k2 + 2k3 + k4 )




 zi+1


z
0 = y0

3.4 Implémentation
Pour comparer les différents schémas, partons de l’équation différentielle suivante :

y 0 = −ty + t, t ∈ [0, 4]
y(0) = 0
.

On a donc f (t, y) = −ty + t :


function a = f(t, y)
a = -t*y + t
endfunction

On définit les fonctions associées aux différents schémas 3.7, 3.10, 3.9 et 3.11.
function b = euler(n, func)
y=zeros(n)
h = (t2 - t1) / n
y(1) = y0

for i=1:n-1
y(i+1) = y(i) + h*func(t1+i*h, y(i))
end
b = y
endfunction
Code Scilab 3.1 – Schéma d’Euler

31
function c = euler_cauchy(n, func)
y=zeros(n)
y(1) = y0
h = (t2 - t1) / n

for i=1:n-1
k1 = func(t1+i*h, y(i))
k2 = func(t1+i*h + h, y(i) +h*k1)

y(i+1) = y(i) + h/2*(k1 + k2)


end
c = y
endfunction
Code Scilab 3.2 – Schéma d’Euler-Cauchy

function d = pt_milieu(n, func)


y = zeros(n)
y(1) = y0
h = (t2 - t1) / n

for i=1:n-1
k1 = func(t1+i*h, y(i))
k2 = func(t1+i*h + h/2, y(i) + (h/2)*k1)

y(i+1) = y(i) + h*k2


end
d = y
endfunction
Code Scilab 3.3 – Schéma du point milieu

function e = runge(n, func)


y = zeros(n)
y(1) = y0
h = (t2 - t1) / n

for i=1:n-1
k1 = func(t1+i*h, y(i))
k2 = func(t1+i*h + h/2, y(i) + (h/2)*k1)
k3 = func(t1+i*h + h/2, y(i) + (h/2)*k2)
k4 = func(t1+i*h + h, y(i) + h*k3)

y(i+1) = y(i) + h/6*(k1 + 2*k2 + 2*k3 + k4)


end
e = y
endfunction
Code Scilab 3.4 – Schéma de Runge-Kutta

Dans le futur, au lieu d’utiliser ces fonctions personnalisées, on utilisera la macro ode de
Scilab pou résoudre des équations différentielles.

32
3.5 Applications

3.5.1 Pendule simple


Un pendule simple de longueur L suit l’équation de mouvement suivante :

= − Lg sin θ(t)

00
θ (t)



θ(0) = θ0 . (3.12)
 0

θ (0) =0

Avec θ0 l’angle initial du pendule. On considère que la vitesse angulaire initiale est nulle.
Pour résoudre cette équation, on effectue une linéarisation de sin θ, en approchant sin θ par
θ pour les petits angles.
Le nouveau système est donc :

= − Lg Φ(t)

00
Φ (t)


Φ(0) = θ0 , (3.13)

 0

Φ (0) =0

dont la solution est


g
r 
Φ(t) = θ0 cos t .
L
Mais cette solution n’est valide que pour des angles assez petits. On peut se demander à
partir de quelle valeur de θ0 cette solution est satisfaisante. On compare donc la solution
linéarisée avec la solution approchée par la macro ode de l’équation originale.

Figure 3.1 – Comparatif entre la solution harmonique et la solution numérique

33
On voit avec la figure 3.1 que plus l’angle de départ est élevé, plus les solutions se déphasent
rapidement. Le choix de l’angle critique dépend de la durée de l’expérimentation, mais un
angle de départ supérieur à π8 semble être une borne supérieure large pour valider la solution
linéarisée.

3.5.2 Mécanique céleste


En physique, il est commun de calculer le mouvement de deux corps en attraction gravita-
tionnelle. Ce problème a été résolu, les corps effectuent des trajectoires coniques ayant pour
foyer le centre de gravité du système.
Lorsqu’un troisième corps entre en jeu, les choses se compliquent et la résolution analytique
est plus complexe. On appelle ce problème le problème des trois corps.
Simulons dans Scilab le comportement de ces corps, tout d’abord lorsqu’il y en a seulement
deux.
Soit u1 et u2 les positions de deux corps célestes. Les forces, et donc les accélérations exercées
sur les corps sont décrites par le système :


00
u2 − u1
u1 = Gm2



||u2 − u1 ||3 , (3.14)

00
u2 − u1
u2 = −Gm1



||u2 − u1 ||3
avec ! !
x x
u1 = 1 , u2 = 2
y1 y2

On transforme ce problème de second ordre en problème de premier ordre solvable par la


macro ode en définissant :

u1
 
u0 
v =  1 .
 
u2 
u02
On a alors :
 
u01
 Gm u2 − u1 
 
 
2

||u2 − u1 || 
3
v 0 = f (v) =  (3.15)
 
0
u

2
 
 
 u2 − u1 

−Gm1 
||u2 − u1 ||3

34
Ce qui nous donne la fonction Scilab :
function dvdt=gravit(t,v)
m1 = 5.975e24;
m2 = 7.35e22;
G = 6.67e-11;

u1 = [v(1); v(2)]
u1prime = [v(3); v(4)]
u2 = [v(5); v(6)]
u2prime = [v(7); v(8)]

dvdt = [u1prime;
G*m2*(u2-u1)/(norm(u2-u1)^3);
u2prime;
-G*m1*(u2-u1)/(norm(u2-u1)^3)]
endfunction

On peut directement simuler le mouvement de la Terre et de la Lune avec les bonnes condi-
tions initiales :

u1 (0) = (0, 0) , u2 (0) = (dT L , 0) ,



u01 (0) = (0, 0) , u02 = (0,
dT L ) ,
T
avec dT L la distance Terre-Lune et T la période de rotation de la Lune autour de la Terre, et
en utilisant les masses appropriées.
T = 27.55*24*60*60
dtl = 3.84402*10^8
v0 = [0; 0;
0; 0;
dtl; 0;
0; 2*%pi/T*dtl]

t = linspace(0, 5*T, 1000)


v = ode(v0, 0, t, gravit)

Grâce à la macro comet, on peut afficher l’animation de l’orbite de la lune autour de la terre.
On visualise ainsi que la Lune a bien un effet sur la position de la Terre, qui a l’air non-
négligeable puisqu’on peut remarquer la trajectoire circulaire de celle-ci (figure 3.3).
La prochaine étape est d’ajouter un troisième corps dans le système. On a alors :
 
u1
 0
u1 
u2 
 
v=
u0  .

 2
u3 
 

u03

35
Figure 3.2 – Mouvement du système Terre-Lune

Figure 3.3 – Repère centré sur le centre de gravité

Figure 3.4 – Ajout d’un troisième corps au point de Lagrange

On place le troisième corps de 1 kg au quatrième point de Lagrange, c’est à dire que ce corps
sera immobile par rapport à la Terre et à la Lune.
√ √
dT L 3 3 π
u3 (0) = ( , dT L ), u03 (0) = (−dT L π , dT L ) .
2 2 T T

3.5.3 Attracteur étrange


Avec la même méthode, on peut implémenter un système dynamique de Lorentz, et plus
précisément un attracteur étrange.
Le système dynamique différentiel de Lorentz s’écrit sous la forme :

0
x

 = σ(y − x)

y0 = ρx − y − xz . (3.16)
 0

z = xy − βz

36
Ce qui nous donne le vecteur v :
 
x
v= y  ,
 

z
 
σ(y − x)
0
v = f (v) = ρx − y − xz  .
 

xy − βz

Ici, pas besoin de ramener les équations à l’ordre 1, car elles le sont déjà toutes.
La fonction Scilab est donc :
function dvdt=f(t,v)
dvdt(1)=sig*(v(2)-v(1))
dvdt(2)=rho*v(1)-v(2)-v(1)*v(3)
dvdt(3)=v(1)*v(2)-bet*v(3)
endfunction

Si on prend σ = 10, ρ = 28 et β = 8/3, on obtient l’attracteur étrange en forme d’ailes de


papillon (figure 3.5). Les conditions initiales sont arbitraires. On peut représenter à l’aide de
la macro comet3d l’animation d’un point qui erre sur l’attracteur dans l’espace.

Figure 3.5 – Attracteur étrange de Lorentz

3.5.4 Modèle proie-prédateur


Grâce aux équations de Lotka-Volterra, il est possible de simuler l’évolution de la population
de proies et de prédateurs dans un système isolé.
Le système est de la forme :

 x0 = αx − βxy
0
. (3.17)
y = Σxy − γy

37
Ici, x représente le nombre de proies, et y le nombre de prédateurs. On remarque que si il
n’y a pas de prédateurs (y = 0), la nombre de proies augmente exponentiellement (x0 =
αx). De la même façon, sans proies, le nombre de prédateurs décroît exponentiellement.
Les paramètres α, β, Σ, γ représentent les taux de mortalité et de reproduction des proies et
prédateurs.
function dvdt=f(t,v)
dvdt(1)=a*v(1)-b*v(1)*v(2)
dvdt(2)=c*v(2)*v(1)-d*v(2)
endfunction

Quand on visualise l’évolution en fonction du temps (figure 3.6), on remarque une solution
périodique. Quand le nombre de proies est minimal, la population de prédateurs décroît le
plus rapidement, puis, quand la population de prédateurs est au minimum, la population
de proies augmente le plus vite.

Figure 3.6 – Modèle proie-prédateur en fonction du temps

La dimension cyclique est flagrante quand on visualise l’évolution des proies en fonction
des prédateurs, pour différentes conditions initiales (figure 3.7).

Figure 3.7 – Evolution des proies en fonction des prédateurs

38
Chapitre 4

Valeurs propres et applications

4.1 Décomposition en valeurs singulières (SVD)


La décomposition en valeurs singulières d’une matrice fournit un outil important de traite-
ment de données. Elle permet de factoriser des matrices rectangulaires, qui est la base de la
compression de données, par exemple d’images.

4.1.1 Théorie
Soit M une matrice rectangulaire m ∗ n avec des coefficients réels. M peut alors être décom-
posée sous la forme

M = U ΣV T , (4.1)

avec U une matrice unitaire m x m, V T la transposée d’une matrice unitaire n x n, et Σ une


matrice m x n dont les coefficients diagonaux sont positifs ou nuls et tous les autres sont
nuls. Si on choisit de trier ces coefficients par ordre décroissant, on a unicité de Σ.
 
σ1 0 ··· 0
 .. 
0

σ2 .
 .. ...
 
 . 0

Σ=   , σ1 ≥ σ2 ≥ · · · ≥ 0
0
 ··· ··· σn 

0 ··· ··· 0
 

.. .. 
. .

Les coefficients diagonaux de Σ sont les valeurs singulières de M . Soit r le nombre de valeurs
singulières non nulles, on a :

M V = σi Vi , 1 ≤ i ≤ r
i
M V i = 0 , 1 + r ≤ i ≤ n,

39
ce qui nous donne :

r
σi Ui ViT .
X
M=
i=1

On peut alors approcher M par Mk en arrêtant de sommer lorsque σi est suffisamment petit.
En effet, on a :

||M − Mk ||2F = σn+1


2
,
avec
k
σi Ui ViT .
X
Mk =
i=1

4.1.2 Application : Compression d’images


Cette méthode d’approximation permet de compresser des images. Prenons une image de
n x n pixels. Si l’image est stockée dans une matrice n x n, on a besoin de stocker n2 entiers
(couleur des pixels, ou niveau de gris).
En appliquant l’approximation avec la SVD, il nous suffit de choisir un certain k pour pou-
voir calculer Mk . Il suffit alors de stocker k vecteurs U i de taille n, k vecteurs de taille n, et k
valeurs singulières, réduisant ainsi à k(2n + 1) le nombre d’entiers à stocker.
Bien sûr, plus on choisit un k petit, plus la qualité de l’image compressée baisse, et moins
elle prendra de place à stocker.

Figure 4.1 – Lena non compressée

Dans Scilab, la macro svd permet d’obtenir directement les matrices U , Σ, et V . On peut
alors facilement compresser Lena, en choisissant un certain k. Pour choisir k, on peut le faire
graphiquement en visualisant les valeurs singulières et en regardant quels σi sont insigni-
fiants devant σ1 . La figure 4.3 nous montre qu’à partir de k = 30, les valeurs propres sont
inférieures à 2% de la valeur propre dominante σ1 , c’est donc la valeur qu’on utilise dans le
programme 4.1.

40
Figure 4.2 – σk /σ1 en fonction de k

l = read('lena.csv', 512, 512)


lena = l'
x=[1:512]
y=[512:-1:1]

[U, S, V] = svd(lena)
sig = diag(S)

k = 30

Ak = sig(1)*U(:,1)*V(:,1)'

for i=2:k
Ak = Ak+sig(i)*U(:, i)*V(:, i)'
end
Code Scilab 4.1 – Compression d’image

Figure 4.3 – Compression de Lena (k = 30)

Taux de compression

Le taux de compression est égal à la taille des données divisée par la taille des données
n2
compressées. Pour une image de n x n, il est de k(2n+1) . Ici, on a n = 512 et k = 30, on a donc

41
T = 8.53. La compression a donc permis d’utiliser 8 fois moins de place en mémoire.

Figure 4.4 – Taux de compression en fonction de k

PSNR

Le Peak Signal to Noise Ratio permet de mesurer la qualité de la compression par rapport à
l’image originale. Il est défini par :
!
d2
P SN R = 10 log10 ,
M SE
avec d = 256 la valeur maximale que peut prendre un pixel et M SE l’erreur quadratique
moyenne :

n X n
1 X
M SE = 2 (A(i, j) − Ak (i, j))2 .
n i=1 j=1

Plus le P SN R (en dB) est élevé, plus la compression est de bonne qualité. On voit que plus
on prend un k élevé, plus la compression est fidèle à l’originale.

Figure 4.5 – PSNR (dB) en fonction de k

42
4.2 Méthode des puissances
Le calcul des valeurs propres n’est pas toujours facile, par exemple pour des matrices conte-
nant beaucoup de données. La méthode des puissances permet de calculer de manière itérée
la valeur propre dominante d’une matrice ainsi que son vecteur propre associé.

4.2.1 Théorie
Soit A une matrice carrée d’ordre n et soit λ1 sa valeur propre dominante (|λ1 | > max(|λ2 |, · · · , |λn |))
et v1 un vecteur propre associé. Alors, si on prend un x0 non orthogonal à v1 , la suite

xn+1 = Axn

vérifie

xn v1
−→ .
||xn || ||v1 ||

Cette méthode permet d’obtenir le vecteur propre associé à la valeur propre dominante en
itérant à partir d’un vecteur quelconque.

4.2.2 Application : PageRank


PageRank est l’algorithme utilisé par Google pour mesurer l’importance d’une page web,
c’est donc un indicateur qui permet de classer les pages Web pour le moteur de recherche.
Il est basé sur les références (hyperliens) pointant vers les pages Web. Plus une page Web est
référencée depuis d’autres pages, plus elle est jugée pertinente (d’autant plus que les pages
qui la référencent sont elles-même pertinentes). Il ne suffit donc pas de compter naïvement
le nombre de références sur cette page Web.
La technique utilisée par Google est celle d’une marche aléatoire. Imaginons un utilisateur
qui, à chaque fois qu’il visite une page, clique aléatoirement sur un des liens, le redirigeant
ainsi vers une nouvelle page. Si on réitère ce processus un grand nombre de fois, on peut
trier les pages selon le nombre d’apparitions de celles-ci pendant la marche aléatoire de
l’utilisateur.
En pratique, Google stocke une matrice d’adjacence (modifiée) entre toutes les pages Web, et
calcule le vecteur propre associé à la valeur propre dominante. Cette matrice ayant plusieurs
milliards de colonnes et de lignes, il est impossible de calculer ce vecteur avec les méthodes
classiques, il faut utiliser la méthode des puissances.

43
Matrice d’adjacence

Pour comprendre comment est construite cette matrice d’adjacence, prenons un exemple.
Supposons que le Web est composé de trois pages Web P1 , P2 et P3 , qui se référencent comme
sur la figure 4.6.

Figure 4.6 – Références entre 3 pages Web

On construit d’abord une matrice C carrée d’ordre 3 telle que :



1 si il existe un lien de Pj vers Pi
C(i, j) =
0 sinon

Dans notre exemple, on a :


 
0 0 0
C = 1 0 1 .
 

1 0 0

On normalise les colonnes, pour que C(i, j) représente la probabilité de cliquer sur un lien
vers Pi depuis Pj .
On définit alors H :

C(i, j)
H(i, j) = P
n ,
C(k, j)
k=1

On a ainsi la somme de chaque colonne qui est égale à 1.


Notre matrice devient :
 
0 0 0
H = 0.5 0 1 .
 

0.5 0 0

Le classement des pages peut être exprimé à l’aide d’un vecteur stationnaire I, tel que :

I = HI ,
en d’autres termes, on cherche un vecteur propre de la valeur propre λ = 1.

44
Calcul du vecteur propre

Pour calculer le vecteur propre I associé à la valeur propre dominante λ = 1, on utilise la


méthode de la puissance. On part donc d’un vecteur quelconque I0 (on prendra le vecteur
où toutes les probabilités sont égales) et on calcule, pour k grand, Ik = H k I0 . En pratique, on
préfère normaliser les vecteurs à chaque étape pour éviter d’avoir des valeurs trop grandes.
On a donc la boucle suivante, avec n le nombre de pages :
function I=calcVect(H)
I=zeros(n, 1)
I(:) = 1/n
for i=1:100
if(I == A*I)
break;
end
I = A*I
I = I/sum(I)
end
endfunction
Code Scilab 4.2 – Calcul du vecteur propre avec la méthode des puissances

On choisit donc k = 100, mais on sort de la boucle dès que le vecteur I ne change plus, on a
donc I = AI.

Premier problème

Revenons à notre exemple (4.6). On a :


   
0 0 0 1/3
H = 0.5 0 1 , I = 1/3
  
.
0.5 0 0 1/3
     
0 0 0
2 3
HI =  0.5  , H I = 1/6 , H I = 0 .
     

1/6 0 0
On voit que Ik tend vers le vecteur nul. C’est un problème qui apparaît quand une des
colonnes de H est nulle, c’est à dire quand il existe une page qui ne référence personne.
Cette page "aspire" donc l’importance des autres pages, sans en donner. Pour résoudre ceci,
on imagine qu’un utilisateur se retrouvant sur une page sans lien décide de naviguer sur
une autre page choisie au hasard. Comme si la page sans lien possédait des liens vers toutes
les pages, on remplace les zéros des colonnes nulles par des 1/n, avec n le nombre de pages
au total.
On appelle notre nouvelle matrice S :
 
0 1/3 0
S = 0.5 1/3 1

.
0.5 1/3 0

45
Et on trouve un vecteur stationnaire I :
 
0.1818
I = 0.5454

.
0.2727

La ligne i représente l’importance de la page Pi . On voit donc que P2 l’emporte, suivie de P3


puis de P1 , comme on aurait pu le deviner en regardant la figure 4.6.

Deuxième problème

Prenons un autre exemple.

Figure 4.7 – Deuxième exemple

Dans cette configuration, on a :


 
0 0 0 0 1
1 0 0 0 0


0 1 0 0 0
 
S=
0
.
 0 0 0 0
0 0 1 0 0
 

0 0 0 1 0

Dans ce cas, Ik ne converge pas, car la seconde valeur propre de S est aussi égale à 1. Pour
garantir que |λ2 | < 1, il faut que S soit primitive. On rencontre un problème similaire si des
composants de I sont nuls, ce qui arrive quand un ensemble de pages ne contient pas de
liens vers l’extérieur de ce groupe, cet ensemble aspire donc l’importance des autres pages.
Pour résoudre ces problèmes, il faut que S soit primitive et stochastique.
On définit alors une nouvelle matrice :

1
G = αS + (1 − α) 1n,n ,
n

46
avec 1n,n la matrice remplie de 1, α qui représente la probabilité que l’utilisateur choisisse
un des liens de S, et 1 − α la probabilité qu’il navigue aléatoirement vers une des pages.
Si α = 0, on se ramène à une navigation aléatoire du web. Il faut donc choisir une valeur
proche de 1, pour que la structure de web pèse un poids important. Google choisit un α égal
à 0.85. Pourquoi cette valeur précisément ? Secret de fabrication.

Implémentation

Appliquons maintenant cette méthode à l’ensemble de pages 4.8.

Figure 4.8 – Exemple d’application

Les relations entre les pages sont stockées dans une matrice, où la ligne i représente la liste
des pages référencées par la page i. Des zéros sont rajoutés pour que la matrice soit valide.
E = [2 9 0 0
5 3 7 0
2 6 8 0
3 12 0 0
1 10 0 0
10 11 0 0
10 11 0 0
4 11 12 0
5 6 10 0
13 0 0 0
15 0 0 0
7 11 0 0
9 14 0 0
10 11 13 15
14 12 0 0]
Code Scilab 4.3 – Liste des références décrivant la structure

47
On crée maintenant une première version de la matrice d’adjacence, en utilisant une matrice
sparse de Scilab, car cette matrice est principalement composée de zéros.
k=1
T=zeros(n*n,2)

//parse la structure en matrice sparse


for i=1:size(E,"r")
for j=1:size(E,"c")
if(E(i,j) <> 0) then
T(k,:)=[E(i,j),i]
k=k+1
end
end
end
T=T(1:k-1,:)
H=sparse(T,ones(1,k-1))

On normalise ensuite cette matrice, et on ajoute les probabilités que l’utilisateur navigue
vers une nouvelle page si un page n’a aucune référence.
//normalise
for(c=1:size(H,"c"))
s = sum(H(:,c))
if(s == 0)
H(:,c) = H(:,c) + 1/n
else
H(:,c) = H(:,c)./s
end
end

La dernière version de la matrice prend en compte le paramètre α discuté précédemment.


G = p*H + (1-p)/n*ones(n,n)

Une fonction permet de calculer le vecteur propre grâce à la méthode de la puissance itérée,
en partant d’un vecteur nul.
function X=calcVect(A)
X=zeros(n, 1)
X(:) = 1/n
for i=1:100
if(X == A*X)
break;
end
X = A*X
X = X/sum(X)
end
endfunction

On peut ensuite afficher le vecteur trié et la liste des pages triée par pertinence.

48
Y = calcVect(G)
[S,k]=gsort(Y(:,1),"lr","d")
disp([k, S])

On obtient, pour cet exemple :


13. 0.1313890
15. 0.1299796
14. 0.1210816
10. 0.1125402
11. 0.1108820
9. 0.0773038
12. 0.0763106
7. 0.0504655
5. 0.0399362
6. 0.0387926
2. 0.0283534
1. 0.0269729
3. 0.0243173
8. 0.0168899
4. 0.0147855

On voit donc par exemple que la page la plus pertinente est la page 13, avec un score de
0.13, c’est elle qui sera affichée en premier dans les résultats Google.

49
Chapitre 5

Moindres carrés et régression

La régression est un passage crucial dans l’analyse de données expérimentales. Elle permet
notamment d’établir un modèle à partir d’un ensemble de données expérimentales. Cela
permet par exemple de prévoir les prochains résultats, ou d’établir les relations entre les
différentes variables. Cette régression est obtenue par la méthode des moindres carrés, qui
consiste à minimiser la fonction économique S(θ) pour le jeu de données (xi , yi ), i = 1 . . . N :

N
(f (xi ; θ) − yi )2 ,
X
S(θ) = (5.1)
i=1

où f (x; θ) est le modèle choisi, et θ le vecteur des paramètres.


On définit ainsi θb :

θb = arg minp S(θ) .


θ∈R

5.1 Problème des moindres carrés linéaire

5.1.1 Théorie
On utilise la méthode des moindres carrés linéaire lorsque le modèle y = f (x; θ) dépend
linéairement des θi , c’est-à-dire :

p
X
y= θi φi (x), avec φi : R → R .
i=1

Par exemple, pour un modèle polynomial de degré p, on a :

p+1
θi xi−1 .
X
y=
i=1

On définit le vecteur résiduel r(θ) :

N p !2
= ||r(θ)||2 ,
X X
S(θ) = θk φk (xi )
i=1 k=1

50
avec
r(θ) = Aθ − y ,
   
y1 φ1 (x1 ) . . . φp (x1 )
 .  .. .. 
 ..  ,

y=  A=
 . .  .
yn φ1 (xn ) . . . φp (xn )

Par exemple, dans le cas d’un polynôme de degré 2, on a

1 x1 x21
 
. .. .. 
 ..
A= . . .
2
1 x n xn

On rappelle qu’on cherche θb qui minimise S(θ). Une condition nécessaire est :

∇S(θ)
b = 0. (5.2)

Pour calculer ∇S(θ), on développe S(θ + h) :

S(θ + h) = ||A(θ + h) − h||2 = ||Aθ − y + Ah||2


= (Aθ − y + Ah)> (Aθ − y + Ah)
= ||Aθ − y||2 + 2(Aθ − y)> Ah + ||Ah||2
= S(θ) + ∇S(θ)> h + ||Ah||2

Par identification, on trouve :

∇S(θ) = 2A> (Aθ − y) (5.3)

Une solution du problème des moindres carrés linéaire est donnée par θ,
b solution de

A> Aθb = A> y (5.4)

Preuve :

S(θ) = S(θb + θ − θ)
b
b > (θ − θ)
b + ∇S(θ)
= S(θ) b 2
b + ||A(θ − θ)||
b 2
b + ||A(θ − θ)||
= S(θ)
≥ S(θ)
b

De plus, si rang A = p, θb est unique.

51
5.1.2 Implémentation
Dans Scilab, il faut construire la matrice A en fonction du modèle choisi, puis résoudre (5.4).
Cela peut se faire simplement en écrivant
theta = (A'*A) \ (A'*y)

mais il est équivalent d’écrire


theta = A \ y

Choix du modèle

Prenons un certain jeu de données, généré à partir d’un polynôme bruité pour l’exemple
(figure 5.1).

Figure 5.1 – Données expérimentales

On essaye de chercher un modèle polynomial, mais quel degré choisir ? Quand on trace la
régression pour les 4 premiers degrés (figure 5.2), on voit que la courbe se rapproche de plus
en plus des données. En effet, on verra que l’erreur résiduelle décroît en fonction du degré.
Cependant, il ne faut pas choisir un degré trop élevé, car la régression ne serait plus efficace
pour évaluer de nouvelles données en dehors de l’espace de travail dans lequel sont nos
données actuelles. Comment choisir le modèle optimal, qui minimise l’erreur résiduelle sur
le jeu de données tout en étant capable de prédire de nouvelles données ?

Validation

La clé est de séparer nos données en deux parties distinctes : un ensemble de validation et
un ensemble de travail. L’ensemble de travail va nous permettre d’établir les différents mo-
dèles que l’on souhaite tester, et l’ensemble de validation joue le rôle de nouvelles données
qui n’ont pas servies dans l’apprentissage de la régression. Ainsi, on peut calculer l’erreur
résiduelle sur l’ensemble de validation et la comparer à l’erreur sur l’ensemble de travail.
En Scilab, on peut écrire une fonction de régression qui prend en compte un ensemble de
validation.

52
Figure 5.2 – Régression pour les premiers degrés

function [theta, err, errV]=LLS(t, y, p, v)

tv = t(v)
[tt, k] = setdiff(t, tv)

yv = y(v)
yy = y(k)

A = ones(length(tt),1)
for k=1:p
A(:, k+1) = tt.^k
end

theta = A\yy

err = norm(A*theta-yy)^2 / length(yy)


errV = norm(calcPol(t, theta)-y)^2 / length(y)
endfunction
Code Scilab 5.1 – Fonction de régression avec validation

Ici la fonction calcPol permet d’évaluer un polynôme à partir du vecteur de paramètres.


function y=calcPol(x, theta)
y=zeros(x)
for k=1:size(theta, "r")
y = y + theta(k)*x.^(k-1)
end
endfunction
Code Scilab 5.2 – Évalutation d’un polynôme

53
Le choix de l’ensemble de validation est arbitraire. Par exemple, on choisit que les données
avec |t| < 1.5 sont les données de validation, les autres données servent à construire les
modèles.

Figure 5.3 – Régression avec validation pour les premiers degrés

Comme on le voit sur la figure 5.3, au degré 5, la régression commence à s’éloigner de l’en-
semble de validation, et pour le degré 6, il est flagrant que le modèle n’est pas adapté aux
données. Le degré du modèle est donc inférieur à 6. Pour connaître le modèle optimal, on
peut tracer l’erreur de validation en fonction du degré (figure 5.4).

Figure 5.4 – Erreur de validation

On observe que même si l’erreur résiduelle sur l’espace de travail diminue, l’erreur sur
l’espace de validation atteint un minimum quand le degré est égal à 4. Au-delà, la régression
essaye trop de "fit" les données, on dit qu’il y a "overfitting", ou surapprentissage. Si on
prenait un nombre de paramètres égal au nombre de données, l’erreur résiduelle serait nulle,
car la régression passerait par tous les points, mais ce modèle ne serait pas adapté du tout
pour évaluer des nouvelles données.

54
5.1.3 Restauration d’une image
La régression permet aussi d’améliorer la qualité visuelle d’une image bruitée. C’est ce qu’on
va faire avec l’image 5.5, de 65x65 pixels.

Figure 5.5 – Image bruitée

Chaque pixel est représenté par son intensité lumineuse. L’image peut donc être stockée
dans une matrice Z à n lignes et n colonnes, avec n = 65. Pour débruiter l’image, on cherche
à approcher les termes zij par une fonction polynomiale de la forme :

fc (i, j) = c1 + c2 i + c3 j + c4 ij . (5.5)

On cherche donc à déterminer le vecteur C des coefficients :

c1
 
c 
 2
c= ,
c3 
 

c4

de manière à minimiser la fonction de coût quadratique :

n X
n
(zij − fc (i, j))2 .
X
J(c) =
i=1 j=1

55
On définit :
 
z1,1
 . 
 . 
 . 
 
 zn,1 
 
 z1,2 
 
 . 
 . 
 . 
 
z 
b=  n,2  .
 . 
 . 
 . 
 . 
 . 
 . 
 
z 
 1,n 
 . 
 . 
 . 
zn,n

On cherche à avoir
J(c) = ||Ac − b||2 ,

On pose alors A une matrice n2 x4 telle que :


 
1 1 1 1
1 2 1 2
 
 .. .. .. .. 
 
. . . . 
 
1 n 1 n
 
1 1 2 2
 
 
1 2 2 4
A=
. . .
,
. . . .. 
. . . . 

1 n 2 2n
 
. .. .. .. 
 
 .. . . . 
 
. .. .. .. 
.
. . . .  
1 n n n2
où le terme de la dernière colonne est la multiplication des termes des deuxième (i) et troi-
sième (j) colonnes.
Pour construire la matrice A, on écrit une fonction Scilab :
function o=getA(n)
o = zeros(n^2,4)
o(:,1)=1
for j=1:n
for i=1:n
o(i+(j-1)*n,1)=1
o(i+(j-1)*n,2)=i
o(i+(j-1)*n,3)=j
o(i+(j-1)*n,4)=i*j
end
end
endfunction

56
Pour obtenir b à partir d’une image nxn, on a la fonction :

function o=getB(z)
n = size(z, "c")
o = zeros(n^2)
for j=1:n
for i=1:n
o(i+(j-1)*n,1)=z(i,j)
end
end
endfunction

Dans Scilab, pour obtenir la solution c qui minimise la fonction de coût à partir de l’image,
il suffit d’écrire :
load("image.dat", "Z")
c = getA(65)\getB(Z)

Il faut maintenant construire la nouvelle image à partir des paramètres trouvés :


function o=getNewZ(c, n)
o = zeros(n,n)
for j=1:n
for i=1:n
o(i,j)=c(1)+c(2)*i+c(3)*j+c(4)*i*j
end
end
endfunction

On obtient alors l’image débruitée 5.6, qui a donc un gradient de couleur continue car fc est
continue.

5.2 Problème de régression non-linéaire


Soit un jeu de données qu’on cherche à approcher par une fonction de la forme :

f (t) = exp(a + bt + ct2 ) , (5.6)

avec a, b, c à déterminer pour minimiser la fonction de coût. Cette fonction n’est pas linéaire
par rapport aux paramètres, il faut donc utiliser la macro lsqrsolve de Scilab.
Après avoir chargé le jeu de données (t, y), on définit la fonction qui calcule le vecteur d’er-
reur en fonction des paramètres :
function o=f(p,m)
o = y-exp(p(1)+p(2)*t+p(3)*t.*t)
endfunction

Pour obtenir les paramètres qui minimisent la fonction de coût, il suffit d’appeler :
[p,v]=lsqrsolve([10;10;10],f,size(t,1));

57
Figure 5.6 – Comparaison entre l’image bruitée et débruitée

avec un vecteur de départ arbitraire.


On obtient les paramètres, on peut donc tracer la fonction associée à ces paramètres par
dessus le jeu de données (figure 5.7).

Figure 5.7 – Régression non linéaire avec lsqrsolve

Pour ce problème, on peut aussi penser qu’il existe une autre manière de résoudre le pro-
blème : le log trick, qui transformerait l’équation 5.6 en :

F (t) = a + bt + ct2 .

58
Il suffit d’appliquer le log au vecteur y du jeu de données, puis d’appliquer une régression
linéaire. Implémentons cela pour comparer les résultats.
Le code Scilab est identique à celui d’un problème linéaire classique :
ylog = log(y)
A=[ones(length(t),1), t, t.^2]

plog = A\ylog

Figure 5.8 – Comparaison avec le log trick

Si on trace la courbe associée (figure 5.8), on remarque qu’elle ne correspond pas totalement
au jeu de données.
Si on calcule la norme du vecteur résiduel pour la régression non-linéaire, on obtient 0.342,
alors qu’avec le log trick on a 0.593. On voit donc que le log trick ne parvient pas au même
résultat qu’une régression non-linéaire.

5.3 Méthode du gradient


La méthode du gradient permet de trouver le minimum d’une fonction f (x). Elle est définie
comme la méthode itérative :

xk+1 = xk − ρk gk ,

où gk = ∇f (xk ) et ρk > 0.
A chaque itération, on se déplace légèrement dans la direction opposée au gradient au point
actuel.

59
Prenons la fonction :

1
f (x) = x> Ax − b> x , (5.7)
2
avec !
2 −1
A=
−1 2
!
1
b=
1

Le minimum de cette fonction est en (1, 1), essayons de retrouver ce résultat.


Il faut d’abord définir la fonction dans Scilab :
function out=f(x,A,b)
out=.5*x'*A*x-b'*x;
endfunction

Le choix de ρk est crucial. Trop grand, et on risque de manquer le minimum et d’osciller


autour. Trop petit, et l’algorithme sera beaucoup trop lent. Choisissons tout d’abord un ρk
constant, égal à 0.2.
L’algorithme est donc, pour 50 itérations :
x = zeros(2, 50)
x(:,1) = [0.4; -0.2]

for k=1:49
if(abs(f(x(:,k),A,b)) < 0.01) then
break;
end
gk = A*x(:,k)-b
pk=0.2
x(:,k+1) = x(:,k) - pk*gk
trace(x(:,k))
end

La fonction trace permet de tracer les courbes iso-valeurs de f à un point donné :

function trace(xk)
c=f(xk)-f(xc);
a=sqrt(2*c/d(1));
b=sqrt(2*c/d(2));
N=128;
t=linspace(0,2*%pi,N);
x=P*[a*cos(t);b*sin(t)]+xc(:,ones(1,N));
plot(x(1,:),x(2,:),'linewidth',2)
endfunction

On obtient la figure 5.9. On voit bien qu’à chaque itération, on se déplace perpendiculaire-
ment à la courbe d’iso-valeurs.

60
Figure 5.9 – Méthode du gradient avec ρk constant

Mais il existe un ρk optimal, obtenu à l’aide de la méthode du nombre d’or, qui permet
d’avoir un nombre d’itérations minimal. Cette méthode est similaire à la dichotomie et
trouve un extremum d’une fonction en divisant l’intervalle grâce au nombre d’or. Avec ce
pas, on obtient la figure 5.10, où chaque trajet est perpendiculaire au précédent.

Figure 5.10 – Méthode du gradient avec ρk optimal

61
Chapitre 6

Séries de Fourier

6.1 Théorie
On appelle polynôme trigonométrique toute fonction de la forme :
n
a0 X
Pn (x) = + (ak cos(wkx) + bk sin(wkx)) , (6.1)
2 k=1

avec

w= .
T
On appelle série trigonométrique toute fonction


a0 X
f (x) = + (ak cos(wkx) + bk sin(wkx)) , (6.2)
2 k=1

Si (an ) et (bn ) sont décroissantes et tendent vers 0 à l’infini, alors :

lim Pn (x) existe, pour tout x


n→∞

Si Pn converge uniformément vers f , c’est-à-dire si :

∀ > 0, ∃N ∈ N, ∀x ∈ [0, T ], n > N ⇒ |Pn (x) − f (x)| <  ,


on a :
2ZT
an = f (x) cos(nwx) dx ,
T 0 (6.3)
2 Z T
bn = f (x) sin(nwx) dx
T 0
Le théorème de Dirichlet, généralisé par Jordan, nous dit que, si une fonction f est pério-
dique, dont les discontinuités sont en nombre fini et de première espèce, et qui admet en
tout point une dérivée à droite et à gauche, alors la série de Fourier
a0 X
S(x) = + (ak cos(wkx) + bk sin(wkx))
2 n>0

62
converge, et
+ −

 f (x ) + f (x )

si f discontinue en x
S(x) = 2 .
f (x)

sinon

La convergence est uniforme sur tout intervalle où f est continue.


Il est alors possible d’approcher et de compresser des fonctions périodiques, ou des fonctions
classiques sur un intervalle, en ne stockant que les suites (an ) et (bn ) correspondant à la
fonction.

6.2 Applications

6.2.1 Périodisation d’une fonction


On cherche à représenter sous forme d’une série de Fourier la fonction :

f (x) = x(x − 1) ,
définie sur l’intervalle [0, 1/2].
Plusieurs choix s’offrent à nous pour choisir la fonction périodique associée.

Fonction périodique (T=1/2)

Soit f1 la fonction périodique de période 1/2 vérifiant :

f1 (x) = f (x) , ∀x ∈ [0, 1/2] .

Figure 6.1 – Fonction périodique f1

Calculons les coefficients de la série de Fourier (6.3).

63
2ZT
a0 = f (x) dx
T 0
Z 1/2
a0 = 4 x(x − 1) dx
0
1
a0 = − ,
3

2ZT
an = f (x) cos(wkx) dx
T 0
Z 1/2
an = 4 x(x − 1) cos(4πnx) dx
0
1
an = , ∀n > 0
4π 2 n2

2ZT
bn = f (x) sin(wkx) dx
T 0
Z 1/2
bn = 4 x(x − 1) sin(4πnx) dx
0
1
bn = , ∀n > 0 .
4πn

Dans Scilab, on crée une fonction générale qui calcule une série en fonction des suites (an )
et (bn ).
function y=sf(x, n, an, bn, a0, T)
y=a0/2
for k=1:n
y = y + an(k)*cos(2*%pi/T*k*x)+bn(k)*sin(2*%pi/T*k*x)
end
endfunction

Puis on définit les suites pour cette fonction.


function o=a(n)
o = 1/(4*%pi^2*n^2)
endfunction

function o=b(n)
o = 1/(4*%pi*n)
endfunction

Pour différentes valeurs de n, on obtient la figure 6.2. On remarque que la fonction est bien
approchée au milieu de l’intervalle pour de grandes valeurs de n, mais on remarque systé-
matiquement un problème au niveau des bornes, dû au phénomène de Gibbs.

Fonction paire périodique (T=1)

Le problème rencontré aux bornes est peut-être dû au fait que la fonction f1 n’est pas conti-
nue. Construisons une fonction continue.

64
Figure 6.2 – Transformations de Fourier de f1

Soit f2 la fonction périodique paire de période 1 vérifiant :


f2 (x) = f (x) , ∀x ∈ [0, 1/2] .

Figure 6.3 – Fonction périodique paire f2

Calculons les coefficients de la série de Fourier (6.3).

1
a0 = −
3
1
an = 2 2
π n
bn = 0

Ici, les calculs se font beaucoup plus facilement, car f2 est paire, donc f2 (x) sin(wnx) est
impaire, ainsi bn = 0. Similairement, on a f2 (x) cos(wnx) paire.

65
On a juste à changer les fonctions Scilab :
function o=a(n)
o = 1/(%pi^2*n^2)
endfunction

function o=b(n)
o = 0
endfunction

Figure 6.4 – Transformations de Fourier de f2

On obtient la figure 6.4. On remarque que la transformation de Fourier se rapproche beau-


coup plus rapidement de la fonction de départ. On voit aussi que le problème de Gibbs a
quasiment disparu, et cela parce que f2 est continue.

Fonction impaire périodique (T=2)

La fonction f2 est continue mais pas continûment dérivable. Que se passe-t-il si on construit
une fonction continue et continûment dérivable ?
Soit f3 la fonction périodique impaire de période 2 vérifiant :

f3 (x) = f (x) , ∀x ∈ [0, 1/2] .

On peut construire cette fonction continûment dérivable car f a son minimum en = 0.5,
une des bornes. Si une fonction continûment dérivable est symétrique par rapport à l’une
des bornes et dérivable en ce point, on peut toujours construire une fonction périodique
continûment dérivable comme on vient de le faire.

66
Figure 6.5 – Fonction périodique impaire f3

On calcule les coefficients :

an = 0
(−1)n−1
bn = 4
π 3 n3
function o=a(n)
o = 0
endfunction

function o=b(n)
o = 4*((-1)^n-1)/(%pi^3*n^3)
endfunction

La figure 6.6 nous montre qu’à partir de n = 4, la série et la fonction sont quasi-confondues.
On voit donc bien que la façon de transformer la fonction en une fonction périodique est cru-
ciale et permet, en plus d’éviter le phénomène de Gibbs sur les discontinuités, d’augmenter
la rapidité de convergence de la série.

6.2.2 Équation de la chaleur


La propagation de la chaleur dans un solide uniforme est de la forme :

∂u ∂ 2u
(x, t) − 2 (x, t) = 0 (6.4)
∂t ∂x
On cherche à étudier la propagation de la chaleur dans un cercle. On a donc x qui représente
un angle : x ∈ [0, 2π].
On a de plus les conditions aux limites :

u(0, t) = u(2π, t) ,
∂u ∂u
(0, t) = (2π, t) ,
∂x ∂x
67
Figure 6.6 – Transformations de Fourier de f3

et la condition initiale :

u(x, 0) = f (x) .

On a démontré dans le cours, et on ne le refera pas ici, que la solution est de la forme :

αn cos(nx) exp(−n2 t) ,
X
u(x, t) = (6.5)
n≥0

avec αn les coefficients de la série de Fourier de f :

2Zπ
αn = f (x) cos(nx) , dx .
π 0
La fonction f représente l’état de la propagation de la chaleur au temps t = 0. On choisit
une fonction palier telle que :

1 si x ∈ [π − λ, π + λ] ,
f (x) =
0 sinon

et λ ∈ [0, π] représente la largeur de la zone chauffée au départ.

68
Figure 6.7 – Propagation de la chaleur en fonction de λ

Dans Scilab, il nous suffit de créer les fonctions qui calculent les suites (an ) et (un ) :
function o=a(n, lambda)
o = 2/(n*%pi)*sin(n*%pi+n*lambda)
endfunction

function o=u(n, theta, t, lambda)


o = a(n, lambda)*cos(n*theta)*exp(-n*n*t)
endfunction

Dans le programme, on a remplacé x par θ, mais la résolution reste la même.


On peut alors écrire la fonction qui calcule u à un point donné, à un temps donné, et avec
une précision n = 10.
function o =ut(theta, t, lambda)
a0 = 2*lambda/%pi
o = a0
for k=1:10
o = o + u(k, theta, t, lambda)
end
endfunction

On peut alors animer la propagation de la chaleur au cours du temps, en fonction de λ


(figure 6.7)(cliquer pour voir l’animation).
On voit que plus λ est petit, et donc plus la chaleur est concentrée au début, plus elle se
propage rapidement au démarrage, avant de ralentir au même rythme que les autres λ. On
voit aussi que la température moyenne finale dépend de la taille de la zone chauffée au
départ, et don de l’énergie transmise au système. On remarque que même si la fonction f
n’est pas continue, u prend immédiatement la forme d’une gaussienne continue.

69
Conclusion

Pour finir, j’ai trouvé l’UV très intéressante, elle m’a permis d’appliquer les concepts mathé-
matiques parfois abstraits que j’ai assimilé pendant mon cursus. En faisant MT23 en paral-
lèle, j’ai pu voir directement l’utilité de ce que j’apprenais, comme par exemple les vecteurs
propres et les matrices semblables avec la compression. L’outil Scilab permet de visualiser
rapidement les résultats, ce qui m’a permis de comprendre beaucoup plus rapidement que
n’importe quel poly de maths. J’ai été surpris de voir tout ce qu’on peut faire, même avec
des mathématiques simples. L’algorithme de Google est fondé sur des principes étudiés en
MT23, tout comme la compression d’image et la régression.
Au final, je suis heureux d’avoir fait cette UV, que je considère comme ma préférée jusque
là. Je regrette de n’avoir pas eu assez de temps pour faire plus de recherches personnelles et
jouer avec les algorithmes. J’aurais par exemple aimé manipuler des sources audio avec les
séries de Fourier, étudier la compression d’images plus en détail, ou bien tester l’algorithme
de Google sur un grand ensemble de pages. Mais même si rien de cela n’est dans ce cahier, je
sais que j’ai maintenant les bases et les outils pour aller plus loin (après tout, ce n’est qu’une
introduction aux mathématiques appliquées).

70
Annexe A

Problèmes non linéaires

subplot(221)
xDich = dichotomie(a, b, f, prec, Nmax)
plot(log(xDich(1:$-1) - sol), log(xDich(2:$) - sol), "-or")
a = reglin(log(xDich(1:$-1) - sol)', log(xDich(2:$) - sol)');
title(sprintf("Dichotomie␣:␣ordre␣=␣%f", a), 'fontsize', 3)

subplot(222)
xFixe = ptfixe(1.5, g, f, prec, Nmax)
plot(log(xFixe(1:$-1) - sol), log(xFixe(2:$) - sol), "-og")
a = reglin(log(xFixe(1:$-1) - sol)', log(xFixe(2:$) - sol)');
title(sprintf("Point␣fixe␣:␣ordre␣=␣%f", a), 'fontsize', 3)

subplot(223)
xNewton = newton(1.5, Jf, f, prec, Nmax)
plot(log(xNewton(1:$-2) - sol), log(xNewton(2:$-1) - sol), "-ob")
a = reglin(log(xNewton(1:$-2) - sol)', log(xNewton(2:$-1) - sol)')
title(sprintf("Newton␣:␣ordre␣=␣%f", a), 'fontsize', 3)

subplot(224)
xSec = secante(a, b, f, prec, Nmax)
plot(log(xSec(1:$-2) - sol), log(xSec(2:$-1) - sol), "-oc")
a = reglin(log(xSec(1:$-1) - sol)', log(xSec(2:$) - sol)')
title(sprintf("Secante␣:␣ordre␣=␣%f", a), 'fontsize', 3)
Code Scilab A.1 – Approximation des ordres de convergence

71
Annexe B

Fractales

function drawTriangle(points, n)
xfpoly(points(1,:), points(2,:), -(30 + n*(65/NMAX)))
endfunction

function breakTriangle(points, n)
if(n <= NMAX) then
drawTriangle(points, n)

//longueur du cote du triangle


l = points(1, 2) - points(1, 1)

x = points(1,:);
y = points(2,:);

//sous-triangles
t1 = [0.5*(x - x(1)) + x(1);
0.5*(y - y(1)) + y(1)]
t2 = [0.5*(x - x(1)) + x(1) + l/2;
0.5*(y - y(1)) + y(1)]
t3 = [0.5*(x - x(1)) + x(1) + l/4;
0.5*(y - y(1)) + y(1) + l*sqrt(3)/2]

breakTriangle(t1, n+1)
breakTriangle(t2, n+1)
breakTriangle(t3, n+1)

end

endfunction

set(gcf(), "color_map", oceancolormap(100))


set(gca(), "data_bounds", [0, 1, 0, 1])

NMAX = 7

72
triangle = [0, 1, 0.5;
0, 0, sqrt(3)]

breakTriangle(triangle, 0)
Code Scilab B.1 – Triangle de Sierpiǹski en récursif

function fillSqr(points, n)
xfpoly(points(1,:), points(2,:), -(30 + n*(65/NMAX)))
endfunction

function breakSqr(points, n)
if(n <= NMAX) then
fillSqr(points, n)

//longueur du cote du carre


l = points(1, 2) - points(1, 1)

x = points(1,:);
y = points(2,:);

for k =0:8
if(k <> 4) then //si pas carre du centre
//sous-carre
s = [1/3*(x - x(1)) + x(1) + modulo(k,3)*l/3;
1/3*(y - y(1)) + y(1) + (k-modulo(k,3))/3*l/3]

breakSqr(s, n+1)
end
end
end
endfunction

NMAX = 5
sqr = [0, 1, 1, 0;
0, 0, 1, 1]

set(gcf(), "color_map", oceancolormap(100))


set(gca(), "data_bounds", [0, 1, 0, 1])
set(gca(),"isoview","on")

breakSqr(sqr)
Code Scilab B.2 – Tapis de Sierpiǹski en récursif

function W = trianglech()
A = [1/2 0;
0 1/2]
B1 = [1/2; 0]
B2 = [1/4; sqrt(3)/4]

n = 300000

73
X = zeros(2, n)
W = zeros(2, n)
for i=2:n
p = floor(modulo(100*rand(), 3))
select p
case 1 then
X(:,i+1) = A*W(:,i) + B1
W(:,i+1) = X(:,i+1)
case 2 then
X(:,i+1) = A*W(:,i) + B2
W(:,i+1) = X(:,i+1)
case 0 then
X(:,i+1) = A*W(:,i)
W(:,i+1) = X(:,i+1)
end
end
endfunction

W = trianglech()

plot(W(1,:), W(2,:), ".c", "markersize", 1)


a = gca()
a.axes_visible = "off"
a.box = "off"
Code Scilab B.3 – Triangle de Sierpiǹski en itératif

function W = tapisech()
A1 = [1/3 0;
0 1/3]

n = 400000
X = zeros(2, n)
W = zeros(2, n)
for i=2:n
p = floor(modulo(100*rand(), 9))
if(p <> 4) then
m = modulo(p, 3)
X(:,i+1) = A1*W(:,i) + [floor(p/3)/3; m/3]
W(:,i+1) = X(:,i+1)
end
end
endfunction

W = tapisech()
plot(W(1,:), W(2,:), ".", "markersize", 1)
a = gca()
a.isoview= "on"
a.axes_visible = "off"
a.box = "off"
Code Scilab B.4 – Tapis de Sierpiǹski en itératif

74
function addSqr(s, n)
if(n <= NMAX) then
xfpoly(s(1,:), s(2,:), -60)
a = %pi/4
A1 = [cos(a)^2, -cos(a)*sin(a);
cos(a)*sin(a), cos(a)^2]
A2 = [sin(a)^2, cos(a)*sin(a);
-cos(a)*sin(a), sin(a)^2]

B1 = [0; 1]
B2 = [cos(a)^2; 1+cos(a)*sin(a)]
s1 = zeros(2, 4)
s2 = zeros(2, 4)
for k=1:4
s1(:,k) = A1*s(:,k) + B1
s2(:,k) = A2*s(:,k) + B2
end
addSqr(s1, n+1)
addSqr(s2, n+1)

end

endfunction

NMAX = 10

sqr = [0, 1, 1, 0;
0, 0, 1, 1]
set(gca(), "isoview", "on")
set(gcf(), "color_map", oceancolormap(100))
set(gca(),"data_bounds",[-4, 4, 2, 6])
addSqr(sqr, 0);
Code Scilab B.5 – Arbre de Pythagore en récursif

function W = pyth()

n = 100000
W = zeros(2, n)
a = %pi/4
A1 = [cos(a)^2, -cos(a)*sin(a);
cos(a)*sin(a), cos(a)^2]
A2 = [sin(a)^2, cos(a)*sin(a);
-cos(a)*sin(a), sin(a)^2]

B1 = [0; 1]
B2 = [cos(a)^2; 1+cos(a)*sin(a)]

75
for k=2:n
p = floor(modulo(100*rand(), 2))
select p
case 0
W(:, k+1) = A1*W(:, k)+B1
case 1
W(:, k+1) = A2*W(:, k)+B2
end
end
endfunction

set(gca(),"data_bounds",[0, 1, 0, 1])
set(gca(),"isoview","on")
a = gca()
a.isoview= "on"
a.axes_visible = "off"
a.box = "off"

W = pyth()
plot(W(1,:), W(2,:), ".", "markersize", 1)
Code Scilab B.6 – Arbre de Pythagore en itératif

function W = trianglech()
A1 = [0.85 0.04;
-0.04 0.85]
A2 = [0.2 -0.26;
0.23 0.22]
A3 = [-0.15 0.28;
0.26 0.24]
A4 = [0 0;
0 0.16]

B1 = [0; 1.6]
B2 = B1
B3 = [0; 0.44]
B4 = [0; 0]
P = [0.85 0.07 0.07 0.01]
n = 150000
X = zeros(2, n)

W = zeros(2, n)
for i=2:n
p = rand()
if(p < P(1)) then
X(:,i+1) = A1*W(:,i) + B1
W(:,i+1) = X(:,i+1)
elseif(p < sum(P(1:2))) then
X(:,i+1) = A2*W(:,i) + B2

76
W(:,i+1) = X(:,i+1)
elseif(p < sum(P(1:3))) then
X(:,i+1) = A3*W(:,i) + B3
W(:,i+1) = X(:,i+1)
else
X(:,i+1) = A4*W(:,i) + B4
W(:,i+1) = X(:,i+1)
end
end
endfunction

W = trianglech()
set(gca(), "isoview", "on")
plot(W(1,:), W(2,:), ".", "markersize", 1)
Code Scilab B.7 – Fougère de Barnsley en itératif

77
Bibliographie

[1] Butterfly Curve. url : https://en.wikipedia.org/wiki/Butterfly_curve_(transcendental).


[2] Karen A. Kopecky. Numericel Differentiation. 2007. url : http://www.karenkopecky.
net/Teaching/eco613614/Notes_NumericalDifferentiation.pdf.
[3] D. Levy. Numerical Differentiation. url : http : / / www2 . math . umd . edu / ~dlevy /
classes/amsc466/lecture-notes/differentiation-chap.pdf.
[4] R. Touzani. Dérivation numérique. url : http://math.univ-bpclermont.fr/~touzani/
teaching/an4.pdf.

78