Import des bibliothèques Python

In [1]:
import numpy as np                #pour disposer des tableaux de type array
import matplotlib.pyplot as plt   #pour les graphiques
In [2]:
% matplotlib inline
#pour l'affichage des graphiques dans la page et non pas dans une fenetre pop up
In [4]:
import operator                   #pour utiliser les opérateurs de base sous forme de fonctions
In [5]:
from sympy import *               #pour le calcul formel
init_printing()
t = symbols('t')
In [6]:
def dérivée(exp, t):
    return diff(exp,t)

def simplifier(exp):
    return simplify(exp)

Résolution approchée de $f(x)=0$ par dichotomie, exemple 15 du cours

Soit $f$ la fonction définie sur $\mathbb{R}$ par $f(x)=x^3-3x^2+5$ definie sur $\mathbb{R}$ et dérivable sur $\mathbb{R}$ .

Question 1 : Calcul de dérivée

In [7]:
#expression de f(x)
fexp = t**3 - 3*t**2 + 5
fexp
Out[7]:
$$t^{3} - 3 t^{2} + 5$$
In [8]:
#expression de f'(x)
fprimexp = dérivée(fexp, t)
fprimexp
Out[8]:
$$3 t^{2} - 6 t$$
In [9]:
simplifier(fprimexp)
Out[9]:
$$3 t \left(t - 2\right)$$

Questions 2 et 3 Etude des variations de $f$

In [10]:
f = lambdify(t, fexp,"numpy")
fprim = lambdify(t, fprimexp,"numpy")
In [13]:
#tracé des  courbes  de f et f'
#Message d'erreur pour f' pour le point d'abscisse 0 (division par 0)
xmin, xmax, ymin, ymax = -6, 6, -20 , 20
plt.axis([xmin, xmax, ymin, ymax])
tx = np.linspace(xmin, xmax, 1001)
ty = f(tx)
tz = fprim(tx)
plt.axhline(color='blue')
plt.axvline(color='blue')
plt.grid(True)
plt.plot(tx, ty, linestyle='-', linewidth=2, color='red', label=r'$y=f(x)$')
plt.plot(tx, tz, linestyle='-', linewidth=1, color='green', label=r"$y=f'(x)$")
plt.legend(loc='lower right')
         
Out[13]:
<matplotlib.legend.Legend at 0xaf6e2a8c>

Question 4 Existence de solutions de l'équation $f(x)=4$

  • $f:x \mapsto f(x)=x^3-3x^2+5$ est dérivable donc continue sur $[-2;-1]$
  • $f(-2)<0$ et $f(-1)>0$
  • $f$ est strictement croissante sur $[-2;-1]$

D'après un corollaire du théorème des valeurs intermédiaires, l'équation $f(x)=0$ possède donc une unique solution $\alpha$ dans l'intervalle $[-2;-1]$

Résolution approchée par balayage

In [14]:
def balayage(g, a, b, pas, k):
    """Retourne un intervalle d'amplitude pas encadrant l'unique solution de g(x)= k
    dans l'intervalle [a,b]"""
    if g(a) < k:
        comparaison = lambda u, v : operator.lt(u,v)
    else:
        comparaison = lambda u, v : operator.gt(u,v)
    x = a
    #en-tete du tableau
    print('|{etape:^16}|{t:^12}|{ft:^12}|'.format(etape='Etape', t='t', ft='g(t)'))
    count = 1
    while comparaison(g(x), k):
        print('|{etape:^16}|{t:^12.6f}|{ft:^12.6f}|'.format(etape=count,t=x, ft=g(x)))
        x += pas
        count += 1
    print('|{etape:^16}|{t:^12.6f}|{ft:^12.6f}|'.format(etape=count,t=x, ft=g(x)))       
    return x - pas, x
In [21]:
balayage(f, -2, -1, 0.1, 0)
|     Etape      |     t      |    g(t)    |
|       1        | -2.000000  | -15.000000 |
|       2        | -1.900000  | -12.689000 |
|       3        | -1.800000  | -10.552000 |
|       4        | -1.700000  | -8.583000  |
|       5        | -1.600000  | -6.776000  |
|       6        | -1.500000  | -5.125000  |
|       7        | -1.400000  | -3.624000  |
|       8        | -1.300000  | -2.267000  |
|       9        | -1.200000  | -1.048000  |
|       10       | -1.100000  |  0.039000  |
Out[21]:
$$\left ( -1.1999999999999993, \quad -1.0999999999999992\right )$$
In [26]:
balayage(f, -1.2, -1.1, 0.01, 0)
|     Etape      |     t      |    g(t)    |
|       1        | -1.200000  | -1.048000  |
|       2        | -1.190000  | -0.933459  |
|       3        | -1.180000  | -0.820232  |
|       4        | -1.170000  | -0.708313  |
|       5        | -1.160000  | -0.597696  |
|       6        | -1.150000  | -0.488375  |
|       7        | -1.140000  | -0.380344  |
|       8        | -1.130000  | -0.273597  |
|       9        | -1.120000  | -0.168128  |
|       10       | -1.110000  | -0.063931  |
|       11       | -1.100000  |  0.039000  |
Out[26]:
$$\left ( -1.1099999999999999, \quad -1.0999999999999999\right )$$
In [27]:
balayage(f, -1.11, -1.1, 0.001, 0)
|     Etape      |     t      |    g(t)    |
|       1        | -1.110000  | -0.063931  |
|       2        | -1.109000  | -0.053581  |
|       3        | -1.108000  | -0.043244  |
|       4        | -1.107000  | -0.032919  |
|       5        | -1.106000  | -0.022607  |
|       6        | -1.105000  | -0.012308  |
|       7        | -1.104000  | -0.002021  |
|       8        | -1.103000  |  0.008253  |
Out[27]:
$$\left ( -1.1040000000000008, \quad -1.1030000000000009\right )$$

Résolution approchée par dichotomie

Fonctions Python

In [17]:
def dicho(f,a,b,e, k):
    """valeur approchée à e près de la solution de f(x)=k
    sur [a,b]. On admet que l'utilisateur saisit des paramètres
    où la dichotomie peut s'appliquer. Construit une figure 
    à chaque étape.
    Les valeurs de a et b affichées sont celles en sortie de boucle."""
    etape = 0 #nombre d'étapes
    if f(a) <= f(b):
        #croissant ou du moins passage de - à +
        croissant = True
    else:
        croissant = False
    while b - a > e:
        etape += 1
        #on calcule le milieu du segment [a,b]
        m = (a+b)/2
        #figure
        x = np.linspace(a,b,500)
        y = f(x)
        plt.xlim(a,b)
        if croissant:
            plt.ylim(max(f(a),-50),min(f(b),50))
        else:
            plt.ylim(max(f(b),-50),min(f(a),50))
        plt.plot(x,y,color='red')
        plt.grid(True)
        plt.axhline(k)
        plt.title('a=%.4f et m=%.4f et b=%.4f'%(a,m,b))
        plt.show()
        #fin de la figure
        s = (f(m) - k)*(f(a) - k)
        #si f(m) - k  et f(a) - k sont de meme signe, f(x)=k dans ]m,b[
        if s > 0:
            a = m
        #si f(m) - k  et f(a) - k sont de signes opposés, f(x)=k dans ]a,m]
        else:
            b = m       
    return a, b, etape

def dicho_tab(f,a,b,e, k):
    """valeur approchée à e près de la solution de f(x)=k
    sur [a,b]. On admet que l'utilisateur saisit des paramètres
    où la dichotomie peut s'appliquer. 
    Ne retourne rien mais remplit un tableau avec les valeurs
    de a, b et m aux differentes etapes.
    Les valeurs de a et b affichées sont celles en sortie de boucle"""
    count = 0 #nombre d'étapes
    if f(a) <= f(b):
        #croissant ou du moins passage de - à +
        croissant = True
    else:
        croissant = False
    #en-tete du tableau
    print('|{etape:^16}|{median:^12}|{test:^10}|{binf:^12}|{bsup:^12}|'.format(etape='Etape',
                                                                     binf='a', bsup='b', median='m',
                                                                     test='Choix ?'))
    #première ligne du tableau
    #remplissage de la ligne du tableau
    print('|{etape:^16}|{median:^12}|{test:^10}|{binf:^12}|{bsup:^12}|'.format(etape='initialisation',
                                                                     binf=a, bsup=b, median=str(None),
                                                                     test=str(None)))
    while b - a > e:
        count += 1
        #on calcule le milieu du segment [a,b]
        m = (a+b)/2
        s = (f(m) - k)*(f(a) - k)
        #si f(m) - k  et f(a) - k sont de meme signe, f(x)=k dans ]m,b[
        if s > 0:
            a = m
        #si f(m) - k  et f(a) - k sont de signes opposés, f(x)=k dans ]a,m]
        else:
            b = m
        #remplissage de la ligne du tableau
        print('|{etape:^16}|{median:^12}|{test:^10}|{binf:^12}|{bsup:^12}|'.format(etape=count,
                                                                     binf=a, bsup=b, median=m,
                                                                     test= 'gauche' if b == m else 'droite'))   

Résolution par dichotomie de l'équation $f(x)=4$ dans l'intervalle $[0,1]$

D'abord on s'arrete lorsque l'amplitude de l'intervalle $[a,b]$ est inférieure ou égale à $0,01$

In [18]:
dicho_tab(f, -2, -1, 0.01, 0)
|     Etape      |     m      | Choix ?  |     a      |     b      |
| initialisation |    None    |   None   |     -2     |     -1     |
|       1        |    -1.5    |  droite  |    -1.5    |     -1     |
|       2        |   -1.25    |  droite  |   -1.25    |     -1     |
|       3        |   -1.125   |  droite  |   -1.125   |     -1     |
|       4        |  -1.0625   |  gauche  |   -1.125   |  -1.0625   |
|       5        |  -1.09375  |  gauche  |   -1.125   |  -1.09375  |
|       6        | -1.109375  |  droite  | -1.109375  |  -1.09375  |
|       7        | -1.1015625 |  gauche  | -1.109375  | -1.1015625 |
In [19]:
dicho(f, -2, -1, 0.01, 0)
Out[19]:
$$\left ( -1.109375, \quad -1.1015625, \quad 7\right )$$

Ensuite on s'arrete lorsque l'amplitude de l'intervalle $[a,b]$ est inférieure ou égale à $0,001$

In [20]:
dicho_tab(f, -2, -1, 0.001, 0)
|     Etape      |     m      | Choix ?  |     a      |     b      |
| initialisation |    None    |   None   |     -2     |     -1     |
|       1        |    -1.5    |  droite  |    -1.5    |     -1     |
|       2        |   -1.25    |  droite  |   -1.25    |     -1     |
|       3        |   -1.125   |  droite  |   -1.125   |     -1     |
|       4        |  -1.0625   |  gauche  |   -1.125   |  -1.0625   |
|       5        |  -1.09375  |  gauche  |   -1.125   |  -1.09375  |
|       6        | -1.109375  |  droite  | -1.109375  |  -1.09375  |
|       7        | -1.1015625 |  gauche  | -1.109375  | -1.1015625 |
|       8        |-1.10546875 |  droite  |-1.10546875 | -1.1015625 |
|       9        |-1.103515625|  gauche  |-1.10546875 |-1.103515625|
|       10       |-1.1044921875|  droite  |-1.1044921875|-1.103515625|
In [28]:
dicho(f, -2, -1, 0.001, 0)
Out[28]:
$$\left ( -1.1044921875, \quad -1.103515625, \quad 10\right )$$
In [29]:
n = 0
while 1/2**n > 0.001:
    n += 1
print(n)
10

L'intervalle de départ a pour amplitude 1 ($a_0=-2$ et $b_0=-1$) A chaque étape l'amplitude de l'intervalle de recherche est divisée par 2 Au bout de $n$ étapes, l'amplitude de la zone de recherche est de $\frac{b_{0}-a_{0}}{2^n}$ soit $\frac{1}{2^n}$ ici. Avec la calculatrice (voir ci-dessus ou le logarithme népérien) on peut vérifier que le plus petit entier $n$ tel que $\frac{1}{2^n} \leqslant 0,001$ est $n=10$