Comment créer automatiquement à l’aide de Python et de LaTeX un arbre de Bernoulli en probabilités ?

Je vais vous montrer l’utilisation d’une fonction Python que je viens d’écrire, et que les abonné·e·s trouveront en fin d’article.

LaTeX et Python: exemples d’arbres de Bernoulli

La fonction Python qui créée en LaTeX un arbre de Bernoulli

L’appel de la fonction nécessite obligatoirement deux paramètres: la hauteur de l’arbre et la probabilité du succès. Par exemple,

>>> bernoulli_tree(3,0.2)

va automatiquement créer un fichier \(\LaTeX\) puis le compiler, pour ensuite afficher le PDF:

Comme on peut le remarquer, les points décimaux ont été remplacés par une virgule.

Une arbre de Bernoulli avec des probabilités fractionnaires: l’option “fraction”

Si l’on souhaite que les probabilités s’affichent sous forme fractionnaire, on utilisera l’option “fraction”:

>>> bernoulli_tree(3,0.2,fraction=True,espv=0.7)

Remarquez ici la présence d’un autre paramètre : espv, qui permet d’espacer davantage les nœuds du dernier niveau afin que les fractions s’affichent correctement.

Si la probabilité du succès ne peut pas être écrite sous forme décimale, mais uniquement sous forme fractionnaire, on pourra écrire:

>>> bernoulli_tree(3,'1/3',fraction=True,espx=1,espv=0.8,espvinter=0.5)

Un arbre moins large: l’option espx

>>> bernoulli_tree(3,0.2,espx=1,espv=0.7,espvinter=0.5)

Remarquez ici la présence du paramètre espvinter qui désigne l’espace vertical entre les “groupes” de couples (succès,échec) au dernier niveau.

Par de nom à la racine

Si vous ne souhaitez pas que \(\Omega\) apparaisse à la racine, tapez:

>>> bernoulli_tree(3,'1/3',fraction=True,espx=1,espv=0.8,espvinter=0.5,root='')

Changer les styles

On peut changer les styles TiKZ de tous les objets de l’arbre (branches, nœuds et probabilités):

>>> bernoulli_tree(3,0.2,fraction=True,espv=1.1,espvinter=0.5,stylebranche='line width=1pt,color=blue!50!black',stylenoeud='color=red',styleproba='midway,circle,scale=.5,text=red,draw=red,fill=red!20',filename='arbre-bernoulli-06')

Ici, la seule limite est celle de votre imagination ! Vous pouvez utiliser tous les styles TiKZ que vous souhaitez pour personnaliser votre arbre. Alors, lâchez-vous !

Des fractions écrites “en ligne”

Jouer avec les espaces verticaux est quelques fois pénibles. Dans ce cas, on pourra utiliser la syntaxe suivante:

>>> bernoulli_tree(3,Fraction(3,7),filename='arbre-bernoulli-07')

La fonction Python qui permet de construire en LaTeX un arbre de Bernoulli

Les paramètres utilisés pour la fonction Python permettant de construire en LaTeX un arbre de Bernoulli

  • niveau : nombre entier désignant le niveau de l’arbre (nombre de répétitions de l’expérience de Bernoulli);
  • proba: nombre (float) ou chaîne de caractères (de la forme ‘p/q’) ou objet type Fraction(p,q)
  • succes = ‘S’: lettre désignant le succès. Par défaut, “S”
  • espv = 0.5: espace vertical entre les nœuds “succès/échec”
  • espvinter = 1: espace vertical (en cm) entre les blocs “succès/échec”
  • espx = 2: espace horizontal (en cm) entre chaque niveau
  • fraction = False: booléen pour signifier si les probabilités doivent être écrites sous forme fractionnaire ou non
  • root = ‘$\Omega$’: nom de la racine (syntaxe \(\LaTeX\) mathématique ou pas)
  • stylebranche = ”: style TiKZ des branches
  • stylenoeud = ”: style TiKZ des nœuds (les événements “succès” et “échecs”)
  • styleproba = ‘midway,fill=white,scale=.5’: style TiKZ des probabilités sur les branches
  • filename = ‘arbre’: nom du fichier à sauvegarder et à compiler

Les modules

  • ‘fraction’
    • >>> pip install fractions ou conda install fractions
  • ‘os’ et ‘os.path’ (pour manipulation système: sauvegarde, compilation)

Autres remarques

Il faut bien entendu au préalable avoir installé une distribution \(\LaTeX\).

La fonction Python

from fractions import Fraction

def bernoulli_tree( niveau,\
                    proba,\
                    succes = 'S',\
                    espv = 0.5,\
                    espvinter = 1,\
                    espx = 2,\
                    fraction = False,\
                    root = '$\\Omega$',\
                    stylebranche = '',\
                    stylenoeud = '',\
                    styleproba = 'midway,fill=white,scale=.5',
                    filename = 'arbre'):
    
    # Stéphane Pasquet
    # mathweb.fr
    # 2022/07/02
    # https://www.mathweb.fr/euclide/2022/07/02/latex-et-python-creer-un-arbre-de-bernoulli-automatiquement/
    
    if fraction:
        proba_num = Fraction(str(proba)).numerator
        proba_denom = Fraction(str(proba)).denominator
        if isinstance(proba,float):
            proba_echec_num = Fraction(str(1-proba)).numerator
            proba_echec_denom = Fraction(str(1-proba)).denominator
        else:
            proba_echec_num = Fraction(str(1-Fraction(proba))).numerator
            proba_echec_denom = Fraction(str(1-Fraction(proba))).denominator
        proba = '$\\frac{'+str(proba_num)+'}{'+str(proba_denom)+'}$'
        probaechec = '$\\frac{'+str(proba_echec_num)+'}{'+str(proba_echec_denom)+'}$'
    else:
        probaechec = str(1-proba).replace(".",",")
        proba = str(proba).replace(".",",")
        
    tex = '\\documentclass{standalone}\n'
    tex += '\\usepackage{tikz}\n'
    tex += '\\usetikzlibrary{calc}\n'
    tex += '\\setlength{\\parindent}{0pt}\n'
    tex += '\\begin{document}\n'

    tex += '\\begin{tikzpicture}\n'
    tex += '\\tikzstyle{branche} = [ '+stylebranche+' ]\n'
    tex += '\\tikzstyle{noeud} = [ '+stylenoeud+' ]\n'
    tex += '\\tikzstyle{proba} = [ '+styleproba+' ]\n'
    
    level = niveau
    echec = '\\overline{' + succes + '}'
    
    # placement des noeuds
    
    while level != 0:
        if level == niveau:
            y = 0
            for i in range(2**level):
                if i%2 == 0:
                    tex += '\\node[noeud] (N' + str(level) + '-' + str(i) + ') at ({'+str(espx)+'*'+str(level)+'},'+str(y)+') {$'+succes+'$};\n'
                    y -= espv
                else:
                    tex += '\\node[noeud] (N' + str(level) + '-' + str(i) + ') at ({'+str(espx)+'*'+str(level)+'},'+str(y)+') {$'+echec+'$};\n'
                    y -= espvinter
        else:
            for i in range(2**level):
                if i%2 == 0:
                    tex += '\\node[noeud] (N' + str(level) + '-' + str(i) + ') at ($0.5*(N'+str(level+1)+'-'+str(2*i)+')+0.5*(N'+str(level+1)+'-'+str(2*i+1)+')+(-'+str(espx)+',0)$) \
{$'+succes+'$};\n'
                else:
                     tex += '\\node[noeud] (N' + str(level) + '-' + str(i) + ') at ($0.5*(N'+str(level+1)+'-'+str(2*i)+')+0.5*(N'+str(level+1)+'-'+str(2*i+1)+')+(-'+str(espx)+',0)$) \
{$'+echec+'$};\n'
        
        level -= 1
    
    # tracé des branches
    
    tex += '\\node[left,noeud] at ($0.5*(N1-0)+0.5*(N1-1)+(-'+str(espx)+',0)$) {'+root+'};\n'
    tex += '\\draw[branche] ($0.5*(N1-0)+0.5*(N1-1)+(-'+str(espx)+',0)$) -- (N1-0) node[proba] {'+proba+'};\n'
    tex += '\\draw[branche] ($0.5*(N1-0)+0.5*(N1-1)+(-'+str(espx)+',0)$) -- (N1-1) node[proba] {'+probaechec+'};\n'
    
    for lev in range(1,niveau):
        for i in range(2**lev):
            tex += '\\draw[branche] (N'+str(lev)+'-'+str(i)+'.east) -- (N'+str(lev+1)+'-'+str(2*i)+') node[proba] {'+proba+'};\n'
            tex += '\\draw[branche] (N'+str(lev)+'-'+str(i)+'.east) -- (N'+str(lev+1)+'-'+str(2*i+1)+') node[proba] {'+probaechec+'};\n'

    tex += '\\end{tikzpicture}\n'
    tex += '\\end{document}'
    
    # sauvegarde du fichier LaTeX
    
    from os.path import isfile
    from os import remove, system
    
    if isfile(filename+".tex"):
        remove(filename+".tex")
    
    fichier = open(filename+".tex","x")
    fichier.write(tex)
    fichier.close()

    # compilation PdfLaTeX dans le répertoire courant

    cmd = "pdflatex  --shell-escape -synctex=1 -interaction=nonstopmode "+filename+".tex"
    system(cmd)
    cmd = "START "+filename+".pdf"
    system(cmd)

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