Nous allons voir comment construire le graphique d’une suite avec Python et LaTeX, notamment avec TiKZ, une solution graphique de LaTeX.

Introduction pour construire le graphique d’une suite avec Python et LaTeX

J’avais déjà parlé de cela sur la page https://www.mathweb.fr/euclide/2019/05/21/construire-le-graphe-dune-suite-avec-python/, mais il s’agissait (dans ce dernier article) de construire le graphe directement en Python avec matplotlib.

Les plus averti·e·s d’entre vous, qui utilisent \(\LaTeX\), pourraient avoir envie de construire ce graphe directement avec TiKZ.

Une solution serait d’utiliser pythontex, mais très peu pratique.

Personnellement, je préfère générer le fichier \(\LaTeX\) en Python.

Comment construire le graphique d’une suite en LaTeX à l’aide de Python ?

Dans un premier temps, il faut se mettre d’accord sur la forme de la suite: nous allons considérer une suite \((u_n)\) définie par son premier terme \(u_0\) et par la relation de récurrence \(u_{n+1}=f(u_n)\).

Un premier exemple de graphique d’une suite avec LaTeX et Python

Je considère la suite définie par \(u_0=1\) et \(u_{n+1}=\frac{1}{2}\left(u_n+\frac{7}{u_n}\right)\). J’ai ainsi la fonction \(f(x)=\dfrac{1}{2}\left(x+\frac{7}{x}\right)\).

Avec le programme que j’ai écrit en Python, quand je tape:

>>> G = Graphique_suite( fonction = '0.5*(x+7/x)', \
                     n = 4 , \
                     u0 = 1, \
                     xmin = -1, \
                     xmax = 5, \
                     ymin = -1,\
                     ymax = 5, \
                     stepgrid = 0.5)

>>> G.exportPdf('essai' , values = True)

j’obtiens le PDF suivant:

graphe suite python latex

et le fichier \(\LaTeX\) suivant:

\documentclass{standalone}
\usepackage{tikz}
\begin{document}
\begin{tikzpicture}[baseline=4.8cm]
\draw[dotted,gray,opacity=0.5] (-1,-1) grid[step=0.5] (5,5);
\draw[gray,opacity=0.5] (-1,-1) grid (5,5);
\draw[thick,->,>=latex] (-1,0) -- (5,0);
\draw[thick,->,>=latex] (0,-1) -- (0,5);
\clip (-1,-1) rectangle (5,5);
\draw[thick,orange] plot[domain=-1:5] (\x,\x) node[below left,rotate=45,scale=0.7,outer xsep=3mm] {$y=x$};
\draw[thick,red] plot[domain=0.1:5,samples=100] (\x,{0.5*(\x+7/\x)});
% Graduation des axes
\draw[thick] (1,0.1) -- (1,-0.1) node[below,outer sep=2mm] {1};
\draw[thick] (2,0.1) -- (2,-0.1) node[below,outer sep=2mm] {2};
\draw[thick] (3,0.1) -- (3,-0.1) node[below,outer sep=2mm] {3};
\draw[thick] (4,0.1) -- (4,-0.1) node[below,outer sep=2mm] {4};
\draw[thick] (0.1,1) -- (-0.1,1) node[left] {1};
\draw[thick] (0.1,2) -- (-0.1,2) node[left] {2};
\draw[thick] (0.1,3) -- (-0.1,3) node[left] {3};
\draw[thick] (0.1,4) -- (-0.1,4) node[left] {4};
\draw[dashed,purple] (1,0) node[below,scale=0.5,outer ysep=3mm] {$u_{0}$} -- (1,4.0);
\draw[dashed,purple] (1,4.0) -- (4.0,4.0);
\draw[dashed,purple] (4.0,4.0) -- (4.0,0);
\draw[dashed,purple] (4.0,0) node[below,scale=0.5,outer ysep=3mm] {$u_{1}$} -- (4.0,2.875);
\draw[dashed,purple] (4.0,2.875) -- (2.875,2.875);
\draw[dashed,purple] (2.875,2.875) -- (2.875,0);
\draw[dashed,purple] (2.875,0) node[below,scale=0.5,outer ysep=3mm] {$u_{2}$} -- (2.875,2.654891304347826);
\draw[dashed,purple] (2.875,2.654891304347826) -- (2.654891304347826,2.654891304347826);
\draw[dashed,purple] (2.654891304347826,2.654891304347826) -- (2.654891304347826,0);
\node[below,scale=0.5,outer ysep=3mm,purple] at (2.654891304347826,0) {$u_{3}$};
%
\end{tikzpicture}
\begin{minipage}[t]{40mm}
$u_{0} = 1$\\
$u_{1} = 4.0$\\
$u_{2} = 2.875$\\
$u_{3} = 2.654891304347826$\\
\end{minipage}
\end{document}

La classe Python pour construire le graphique d’une suite

Comme vous pouvez le constater sur l’exemple précédent, on crée un objet “Graphique_suite” avec les instances suivantes:

  • fonction : chaîne de caractères définissant la fonction;
  • n : entier désignant le nombre de termes à placer sur le graphe;
  • u0 : la valeur du premier terme de la suite;
  • xmin et xmax désignent les bornes de l’intervalle sur lequel tracer le graphique;
  • ymin et ymax désignent les bornes de l’intervalle image souhaité;
  • stepgrid : par défaut, cette valeur vaut 0.2; cela correspond aux pointillés de la grille en gris;
  • xscale : l’échelle en abscisse (pour agrandir ou réduire le graphique)
  • yscale : l’échelle en ordonnée
  • valwidth : largeur (en millimètres) de la boîte contenant les valeurs des termes successifs de la suite
  • Df = [ x , y ] : domaine de définition de la courbe à tracer.

Un autre exemple

>>> G = Graphique_suite( fonction = 'sqrt(x)', \
                     n = 7 , \
                     u0 = 0.1, \
                     xmin = -0.2, \
                     xmax = 1.2, \
                     ymin = -0.2,\
                     ymax = 1.2, \
                     stepgrid = 0.1, \
                     xscale = 10, \
                     yscale = 6,\
                     valwidth = 50, \
                     Df = [0,1.2])

>>> G.exportPdf('essai' , values = False)
graphique suite python latex

Un autre exemple

>>> G = Graphique_suite( fonction = 'ln(x+3)', \
                     n = 4 , \
                     u0 = -1, \
                     xmin = -3, \
                     xmax = 3, \
                     ymin = -2,\
                     ymax = 3, \
                     stepgrid = 0.2, \
                     xscale = 2, \
                     yscale = 2,\
                     valwidth = 50, \
                     Df = [-2.8,3])

>>> G.exportPdf('essai' , values = True)
graphique suite latex python

La classe Python

# Classe Graphique_suite
# Author: Stéphane Pasquet
# Date : 2022-05-07
# URL : https://mathweb.fr

from sympy import Symbol, lambdify
from os import system, remove
from os.path import exists
from math import atan, pi

class Graphique_suite:
    def __init__(self,fonction,n,u0,xmin,xmax,ymin,ymax,stepgrid=0.2,xscale=1,yscale=1,valwidth=40,Df=None):
        self.fonction = fonction
        x = Symbol('x')
        self.f = lambdify(x,self.fonction,'math')
        self.xmin = xmin
        self.xmax = xmax
        self.ymin = ymin
        self.ymax = ymax
        self.stepgrid = stepgrid
        self.xscale = xscale
        self.yscale = yscale
        self.valwidth = valwidth
        if Df == None:
            self.Df = [ xmin , xmax ]
        else:
            self.Df = Df
        self.u0 = u0
        self.n = n
        self.U = [ (0,self.u0) ] # self.U = liste des termes successifs (k,u(k))
        for k in range(1,self.n):
            self.U.append( ( k , self.f(self.U[k-1][1]) ) )
        
    def graphique_tex(self,values):
        tex = '\\documentclass{standalone}\n'
        tex += '\\usepackage{tikz}\n'
        tex += '\\begin{document}\n'
        tex += '\\begin{tikzpicture}[baseline='+str((self.ymax-0.2)*self.yscale)+'cm,xscale='+str(self.xscale)+',yscale='+str(self.yscale)+']\n'
        tex += f'\\draw[dotted,gray,opacity=0.5] ({self.xmin},{self.ymin}) grid[step={self.stepgrid}] ({self.xmax},{self.ymax});\n'
        tex += f'\\draw[gray,opacity=0.5] ({self.xmin},{self.ymin}) grid ({self.xmax},{self.ymax});\n'
        tex += f'\\draw[thick,->,>=latex] ({self.xmin},0) -- ({self.xmax},0);\n'
        tex += f'\\draw[thick,->,>=latex] (0,{self.ymin}) -- (0,{self.ymax});\n'
        tex += f'\\clip ({self.xmin},{self.ymin}) rectangle ({self.xmax},{self.ymax});\n'
        tex += f'\\draw[thick,orange] plot[domain={self.xmin}:{self.xmax}] '
        tex += '(\\x,\\x) node[below left,rotate='+str(180*atan(self.yscale/self.xscale)/pi)+',scale=0.7,outer xsep=3mm] {$y=x$};\n'
        tex += '\\draw[thick,red] plot[domain='+str(self.Df[0])+':'+str(self.Df[1])+',samples=100] (\\x,{'+self.fonction.replace('x','\\x')+'});\n'
        tex += '% Graduation des axes\n'
        
        for a in range(int(self.xmin),int(self.xmax)+1):
            if a != 0:
                tex += f'\\draw[thick] ({a},0.1/{self.yscale}) -- ({a},-0.1/{self.yscale}) node[below,outer sep=2mm] '
                tex += '{' + str(a) + '};\n'
        for a in range(int(self.ymin),int(self.ymax)+1):
            if a != 0:
                tex += f'\\draw[thick] (0.1/{self.xscale},{a}) -- (-0.1/{self.yscale},{a}) node[left] '
                tex += '{' + str(a) + '};\n'
    
        for k in range(self.n-1):
            tex += f"\\draw[dashed,purple] ({self.U[k][1]},0) node[below,scale=0.5,outer ysep=3mm] " +  '{$u_{'+str(k)+'}$} -- '
            tex += f"({self.U[k][1]},{self.U[k+1][1]});\n"
            tex += f"\\draw[dashed,purple] ({self.U[k][1]},{self.U[k+1][1]}) -- ({self.U[k+1][1]},{self.U[k+1][1]});\n"
            tex += f"\\draw[dashed,purple] ({self.U[k+1][1]},{self.U[k+1][1]}) -- ({self.U[k+1][1]},0);\n"
            
        tex += f"\\node[below,scale=0.5,outer ysep=3mm,purple] at ({self.U[k+1][1]},0) "
        tex += '{$u_{'+str(self.n-1)+'}$};\n%\n'        
        tex += '\\end{tikzpicture}\n'
        
        if values:
            tex += '\\begin{minipage}[t]{'+str(self.valwidth)+'mm}\n'
            for v in self.U:
                tex += '$u_{'+ str(v[0]) + '} = ' + str(v[1]) + '$\\\\\n'
            tex += '\\end{minipage}\n'
        
        tex += '\\end{document}'
    
        return tex
    
    def exportPdf(self,name,values=False):
        if exists(f'{name}.tex'):
            remove(f'{name}.tex')
            
        fichier = open(f"{name}.tex","x")
        fichier.write(self.graphique_tex(values))
        fichier.close()

        system(f"pdflatex {name}.tex")
        system(f"START {name}.pdf")

0 0 votes
Évaluation de l'article
S’abonner
Notification pour
guest
0 Commentaires
Le plus ancien
Le plus récent Le plus populaire
Commentaires en ligne
Afficher tous les commentaires
0
Nous aimerions avoir votre avis, veuillez laisser un commentaire.x