# CAMA : ma41 Système matriciel non linéaire # Cours du 25 / 06 :::info Si la matrice $A$ dépend de ${\bf x}$ (noté $A({\bf x})$), alors le système matriciel $$ A({\bf x)x = b} $$ **n'est pas linéaire**. ::: **Exemple :** $$ \begin{bmatrix} 1 & x_1 \\ 2x_1 & -x_2 \\ \end{bmatrix} \; \begin{bmatrix} x_{1} \\ x_{2} \\ \end{bmatrix} = \begin{bmatrix} b_{1} \\ b_{2} \\ \end{bmatrix} $$ donne le système suivant non linéaire puisqu'on a des carrés : $$ \begin{align} x_1 + x_1 \, x_2 &= b_1 \\ 2 \, x_1^2 - x_2^2 &= b_2 \end{align} $$ *Comment résoudre un tel système ?* ## La méthode du point fixe :::info La méthode du point fixe consiste à appliquer l'algorithme itératif suivant : $$ {\bf x}^{k+1} = g({\bf x}^k) $$ pour résoudre $g({\bf x}) = {\bf x}$. ::: * $x_0$ donné * ${\bf \bar x} = g({\bf \bar x})$ un point fixe de $g$ * ${\bf x}^{k+1} = g({\bf x}^k)$ avec $k = 0, 1, 2, ...$ ***Est-ce que $g({\bf x}^k)^k$ converge ?*** * Si $\bf{x_0} \lt {\bf \bar x_2}$ : $\lim_{k\to+\infty} = {\bf \bar x_1}$ * Si $\bf{x_0} \gt {\bf \bar x_2}$ : $\lim_{k\to+\infty} = +\infty$ :::warning Selon le point de départ, la méthode converge ou diverge. ::: ### La méthode du point fixe pour résoudre $A({\bf x)x = b}$ :::danger On doit définir une fonction $g$ telle que la solution de $J({\bf x}) = {\bf x}$ soit la solution du système matriciel non linéaire : $$ g({\bf x}) = A^{-1}({\bf x}) \, {\bf b} $$ ::: Inverser A est trop coûteux, on écrit notre algorithme itératif sous forme de problème matriciel linéaire à résoudre: $$ A({\bf x}^k) \, {\bf x}^{k+1} = {\bf b} $$ Si on connait ${\bf x}^k$ on peut évaluer $A({\bf x}^k)$, le système est linéaire et permet de trouver ${\bf x}^{k+1}$. Le fonctionnement de l'algorithme va dépendre du type de la matrice $A$ et de la valeur initiale $x_0$. #### Exemple : $$ \begin{bmatrix} x_0 - 2 x_1 & x_1 \\ x_0 & 2 x_0 + x_1 \\ \end{bmatrix} \; \begin{bmatrix} x_0 \\ x_1 \\ \end{bmatrix} = \begin{bmatrix} 1 \\ 9 \\ \end{bmatrix} $$ Ce système a pour solutions [1, 2] et [2, 1]. ```python= def A(x): return np.array([[x[0] - 2*x[1], x[1]] , [x[0] , x[1] + 2*x[0]]]) / 10 b = np.array([1, 9]) / 10 # avec normalisation grossière x = np.array([1, 1]) for i in range(1, 10): x = lin.solve(A(x), b) ``` ``` ... x^7 = [1.37317932 2.74635363] x^8 = [0.72823777 1.45647516] x^9 = [1.37317809 2.74635608] ``` La solution oscille sans converger. La méthode du point fixe a un petit rayon de convergence. ##### Appliquon l'inertie ```python= µ = 0.5 # on avance de moitié vers le prochain x x = np.array([3, 2]) for i in range(1, 10): x_old = x x = lin.solve(A(x), b) x = µ * x + (1-µ) * x_old ``` ``` ... x^9 = [1.00876429 1.98253948] ``` :::success La convergence est rapide (9 iterations). L'inertie augmente le rayon de convergence : plus $\mu$ est petit plus le rayon de convergence est grand. ::: :::info Pour trouver les autres solutions il faut choisir un autre point initial. ::: ## La méthode de Newton-Raphson :::danger $$ {\bf x}^{k+1} = {\bf x} - \frac{f({\bf x_n})}{f'({\bf x_n})} $$ ::: :::info La méthode de Newton est une méthode de point fixe. $$ {\bf x}^{k+1} = g({\bf x}^k) $$ où $g({\bf x)} = {\bf x} - \frac{f({\bf x})}{f'({\bf x})}$ ::: On souhaite résoudre notre systeme non linéaire. Grâce à la formule ci-dessus, on a en 1D: $$ f'(x^k) \; (x^{k+1} - x^k) = - f(x^k) $$ Ce qui donne en $n$ dimensions: $$ J_{\bf f}({\bf x}^k) \; ({\bf x}^{k+1} - {\bf x}^k) = - {\bf f}({\bf x}^k) $$ avec $J_{\bf f}$ la matrice Jacobienne de ${\bf f}$ : $$ J_{\bf f}\left({\bf x}\right)= \begin{pmatrix} \dfrac{\partial f_1}{\partial x_1} & \cdots & \dfrac{\partial f_1}{\partial x_n} \\ \vdots & \ddots & \vdots \\ \dfrac{\partial f_n}{\partial x_1} & \cdots & \dfrac{\partial f_n}{\partial x_n} \end{pmatrix} $$ Notre système non linéaire avec $f$ une fonction vectorielle: $$ {\bf f}({\bf x}) = A({\bf x})\, {\bf x} - {\bf b} $$ ### Exemple On reprend le système matriciel précèdent. La matrice Jacobienne de la fonciton $f$ est : $$ J_{\bf f}({\bf x}) = \begin{bmatrix} 2 x_0 - 2 x_1 & 2 x_1 - 2 x_0\\ 2 x_0 + 2 x_1 & 2 x_0 + 2 x_1 \\ \end{bmatrix} $$ ```python= def f(x): return A(x) @ x - b def J_f(x): return 2 * np.array([[x[0] - x[1], x[1] - x[0]], [x[0] + x[1], x[0] + x[1]]]) x = np.array([3, 2]) for i in range(30): delta = lin.solve(J_f(x), -f(x)) x = x + delta ``` ``` ... x^29 = [2.05693134 1.05693134] ``` On converge (moins vite) où la methode du point fixe oscille sans converger. :::warning * Le coût de la construction de la matrice Jacobienne peut être tres élevé. * Pour aller plus vite on peut recalculer la matrice toutes les 3 iterations ou plus. * Il s'agit d'une matrice pleine qui rend compliqué la resolution du systeme (une methode de gradient ne marchera pas) :::