Les nouvelles technologies pour l’enseignement des mathématiques
Intégration des TICE dans l’enseignement des mathématiques

MathémaTICE, première revue en ligne destinée à promouvoir les TICE à travers l’enseignement des mathématiques.

Les algorithmes du nouveau lycée technologique, en Python

Savoir (re)créer, en Python, un algorithme faisant des choses basiques est une compétence qui sera évaluée à tous les bacs technologiques à partir de 2020. SofusPy est un outil intéressant pour aborder ces algorithmes.

Article mis en ligne le 31 juillet 2019
dernière modification le 31 juillet 2022

par Alain Busser

Dans cet article, on utilise cette version de SofusPy qui comprend des exemples très proches du programme de sections technologiques et l’outil d’export automatique vers le pseudo-code lui aussi très proche du programme.

Deux notions sont à la base du programme de maths en section technologique : Les compteurs (variables à incrémenter) et les accumulateurs (variables auxquelles on ajoute d’autres variables). L’article leur consacre donc une grande place, ce qui facilite la suite (exemples au programme).

L’article est placé sous licence libre CC-by-SA

Algorithmique et programmation

Variables

Le programme vise à « consolider la notion de variable » par trois « capacités attendues » :

  • utiliser un générateur de nombres aléatoires entre 0 et 1 pour simuler une loi de Bernoulli de paramètre p ;
  • utiliser la notion de compteur ;
  • utiliser le principe d’accumulateur pour calculer une somme, un produit.

Sur les fonctions, deux autres capacités sont mises en exergue :

  • identifier les entrées et les sorties d’une fonction ;
  • structurer un programme en ayant recours aux fonctions.

On va donc utiliser autant que possible le formalisme des fonctions de Python, même pour illustrer le fonctionnement des variables.

Bernoulli

Une variable aléatoire de Bernoulli est un nombre B dépendant du hasard et prenant la valeur 0 avec probabilité 1-p et la valeur 1 avec probabilité p. Or le générateur aléatoire de Python simule une variable aléatoire uniforme entre 0 et 1 qui peut prendre de façon équiprobable toutes les valeurs possibles entre 0 et 1. Une telle variable aléatoire entre 0 et 1 est calculée par une fonction Python notée random(). Or l’événement random()<0.36 a pour probabilité 0,36 comme on peut le constater par exemple on calculant cette probabilité avec la calculatrice :

On admet que la probabilité de l’événement random()<p est égale à p pour toute valeur de p entre 0 et 1, pas seulement pour p=0,36. Pour simuler X, il suffit donc de lui donner la valeur 1 si random()<p et 0 sinon. Comme p est un paramètre, on va construire une fonction dépendant de p pour cela.

Ce qui permet de fabriquer la variable aléatoire avec le script suivant

Fabrication de la fonction

Dans SofusPy, les fonctions sont appelées sous-programmes. On choisit un bloc renvoyant quelque chose dans le menu adéquat, on le renomme (au clavier) B puis on clique sur la roue dentée qui permet de manipuler ses variables d’entrée :

On renomme p la variable qui avait été nommée par défaut x :

Pour créer une variable X, on l’affecte avec ce bloc (extrait du menu des variables) :

C’est dans l’entrée de menu appelée conditionnelles que se trouve le test si...faire...sinon..., ainsi que le bloc d’égalité (à transformer en « inférieur » avec le menu déroulant qu’il comprend). Le bloc alea entre 0 et 1 est dans les fonctions du menu maths. Enfin le X qu’on renvoie se trouve dans le menu des variables. Cela donne la fonction que voici :

Et dans le menu des « sous-programmes », se trouve maintenant un bloc noté B que l’on peut utiliser comme n’importe quelle autre fonction mathématique, dans des expressions algébriques, comme par exemple l’additionner avec autre chose ou la multiplier par 3, etc.

Mais SofusPy est aussi doté d’un bouton « éditeur » :

En cliquant dessus, on accède à un éditeur Python dans lequel se trouve alors ce script :

  1. import random
  2. def B(p):
  3.     global X
  4.     if random.random() < p:
  5.         X = 1
  6.     else:
  7.         X = 0
  8.     return X

Télécharger

Comme l’éditeur Python de SofusPy est un éditeur, on peut utiliser le clavier pour modifier le script. Par exemple on peut

  • remplacer import random par from random import * qui permet de
  • simplifier le random.random() en random() à la ligne 4
  • supprimer la ligne 3 qui est inutile en Python, les variables n’ayant pas besoin d’y être globales (X n’existe que lorsqu’on calcule la fonction B(p) et disparaît sitôt après avoir été renvoyée).
  1. from random import *
  2. def B(p):
  3.     if random() < p:
  4.         X = 1
  5.     else:
  6.         X = 0
  7.     return X
  8.  
  9. print(B(0.36))

Télécharger

La dernière ligne ne fait pas partie de la fonction, elle en est un exemple d’utilisation dans le cas où p=0,36.

Pseudo-code

Noter que dans SofusPy il y a un bouton qui permet de traduire automatiquement le script Python en un pseudo-code similaire à celui des énoncés de bac :

Il produit ceci, à copier-coller dans le cours :

algorithme B(p)
   si random() < p
       X ← 1
   sinon
       X ← 0
   renvoyer X

Simplification

En fait, un test renvoyant 1 si la comparaison réussit et 0 sinon, c’est une fonction qui, à la valeur booléenne True, associe l’entier 1, et à la valeur booléenne False, associe l’entier 0. Cette fonction existe déjà en Python, c’est la conversion d’un booléen en entier et elle s’appelle int() (comme « integer » soit « entier »). Ce qui donne ce script bien plus simple :

  1. from random import *
  2. def B(p):
  3.     return int(random()<p)

Télécharger

Repères historiques : Jakob Bernoulli a inventé la variable aléatoire qui porte son nom parce qu’une somme de telles variables suit une loi binomiale, dont Bernoulli avait besoin pour étudier la fluctuation d’échantillonnage. Ses travaux datent du début du 18e siècle. George Boole a eu vers le milieu du 19e siècle l’idée de représenter la valeur logique faux par un 0 et la valeur logique vrai par un 1, ce qui lui a permis de ramener des opérations logiques (par exemple et ou « and ») à des opérations algébriques (par exemple la multiplication).

Compteur

Un compteur est une variable destinée à être incrémentée, c’est-à-dire qu’on y ajoute 1, soit de façon systématique (alors il sert à calculer le nombre de passages dans la boucle), soit si un test réussit (et dans ce cas il sert à compter les succès).

Par exemple, on voudrait savoir combien de fois il faut lancer un dé pour avoir un 6. Pour cela on va utiliser l’expression randint(1,6) qui donne un nombre pseudo-aléatoire valant 1, 2, 3, 4, 5 ou 6 avec équiprobabilité. Et une variable appelée compteur servira à compter le nombre de lancers.

Simulation d’un lancer du dé

Dans SofusPy, la traduction française de randint(1,6) est entier aléatoire entre 1 et 6 qui prend de la place sur l’écran et nuit à la lisibilité du script. On va donc créer une fonction auxiliaire appelée dé et renvoyant exactement le résultat de l’évaluation de cette expression :

Une fois que cette fonction est définie, on dispose d’un bloc qui peut être utilisé comme n’importe quelle expression algébrique (dans le menu des sous-programmes) :

Par exemple l’expression booléenne comparant le dé avec le nombre désiré 6 :

On peut alors programmer la fonction T (les variables aléatoires mesurant un temps s’appellent souvent ainsi) avec notamment le bloc d’augmentation de 1 présent dans la partie sofus du menu maths :

Le clic sur le bouton éditeur donne alors le script suivant :

  1. import random
  2. def de():
  3.     return random.randint(1, 6)
  4.  
  5. def T():
  6.     global compteur
  7.     compteur = 0
  8.     while de() != 6:
  9.         compteur = compteur + 1
  10.     return compteur

Télécharger

version améliorée

On peut l’améliorer comme dans l’onglet précédent, par exemple

  1. from random import randint
  2. def de():
  3.     return randint(1, 6)
  4.  
  5. def T():
  6.     compteur = 0
  7.     while de() != 6:
  8.         compteur = compteur + 1
  9.     return compteur

Télécharger

En tout cas on y apprend comment réaliser l’incrémentation du compteur :

  1. on évalue l’expression compteur+1 qui donne la nouvelle valeur à donner au compteur
  2. on injecte le résultat de l’évaluation dans la variable compteur ce qui effectue l’incrémentation pour de vrai.

Il y a aussi une autre syntaxe avec un signe d’addition immédiatement suivi d’un signe d’égalité (sans espace entre les deux) qui augmente d’une quantité suivant ce symbole ésotérique, ici 1. Le code compteur += 1 exprime peut-être mieux l’idée de comptage que le fait la version avec évaluation d’expression puis injection dans la variable.

pseudocode

L’algorithme de comptage des lancers de dé s’écrit ainsi en pseudo-code (obtenu en cliquant sur le bouton idoine dans SofusPy avec quelques retouches) :

algorithme dé()
   renvoyer un entier au hasard entre 1 et 6

algorithme T()
   compteur ← 0
   Tant que dé() ≠ 6
       compteur ← compteur + 1
   fin du Tant que
   renvoyer compteur

Compter sans compteur

Pour compter le nombre de 6 parmi 100 lancers de dés, on peut

  1. fabriquer la liste de 200 résultats de test du type randint(1,6)==6 par compréhension ;
  2. demander à Python de compter les True dans cette liste.

Cela donne l’expression [randint(1,6)==6 for k in range(20)].count(True)

Accumulateur

Additionner plusieurs termes

Un accumulateur (informatique) est une variable à laquelle on ajoute successivement des valeurs (pour obtenir leur somme) ou que l’on multiplie par des facteurs successifs (pour obtenir le produit).

Voici un schéma montrant, à gauche, un additionneur (en forme de V) et à droite, un accumulateur :

L’additionneur a deux entrées où l’on injecte les opérandes, et une sortie. L’accumulateur n’utilise qu’une seule des deux entrées, l’autre étant confondue [1] avec la sortie : C’est cette mémoire servant à la fois d’entrée et de sortie, qui sert d’accumulateur. Certaines calculatrices en possèdent une notée M et l’accumulation se fait par le bouton M+.

Par exemple si on veut additionner les nombres affichés par 24 dés, on les additionne un par un (pour k allant de 0 à 23) en mémorisant, au fur et à mesure, les sommes partielles dans l’accumulateur :

Finalement il ne s’agit de rien de plus que de généraliser le comptage, ici les quantités accumulées sont variables alors que dans l’onglet précédent elles valaient toutes 1 (ou 0 si échec). La syntaxe Python est donc très similaire à celle de l’onglet précédent (où a été définie la fonction dé) :

  1. def S24():
  2.     accu = 0
  3.     for k in range(0,24):
  4.         accu = accu + de()
  5.     return accu

Télécharger

pseudocode

SofusPy fournit ce pseudocode, assez explicite :

algorithme S24()
   accu ← 0
   pour k allant de 0 à 23
       accu ← accu + dé()
   renvoyer accu

accumuler sans accumulateur

On a vu dans l’onglet précédent que l’expression [randint(1,6) for k in range(24)] fournit la liste des 24 lancers d’un dé, alors en appliquant à cette liste la fonction sum on obtient le total avec sum([randint(1,6) for k in range(24)]).

Multiplier plusieurs facteurs

Un accumulateur peut aussi être multiplicatif, on le multiplie régulièrement par des facteurs pour qu’il accumule leur produit. Mais dans ce cas sa valeur initiale ne sera pas 0 mais 1 (ou le premier terme u0 d’une suite géométrique).

Par exemple un résultat bien connu des luthiers est que chaque espace entre deux frettes successives dépasse de 6 pourcents l’espace suivant [2]. Et qu’entre la 11e et la 12e frette l’espace est la moitié de l’espace entre la 1ère frette et le sillet de tête. Pour le vérifier avec SofusPy, on compare avec le nombre 2, le résultat de ce script :

Le script annonce 2,0121964718355505 qui n’est effectivement pas loin de 2.

La traduction en Python donnée par SofusPy montre comment on augmente de 6 pourcents :

  1. accmul = 1
  2. for k in range(0,12):
  3.   accmul = accmul + accmul * 6/100

Télécharger

En mettant accmul en facteur dans l’expression de la ligne 3, on vérifie que ce script donne le même résultat :

La version Python est

  1. accmul = 1
  2. for k in range(0,12):
  3.   accmul = accmul * 1.06

Télécharger

Version pseudocode

Le pseudocode correspondant au script Python ci-dessus est

accmul ← 1
pour k allant de 0 à 11
 accmul ← accmul × 1,06

Dans le programme, dans la partie sur les automatismes, il est écrit que cette connaissance que seul Sophus (parmi les langages de programmation) possède, doit être un automatisme :

passer d’une formulation additive ( « augmenter de 5 % », respectivement « diminuer de 5 % » ) à une formulation multiplicative ( « multiplier par 1,05 », respectivement« multiplier par 0,95 » )

Simplification

Comme pour la fonction sum, il y a un moyen rapide de multiplier entre eux les éléments d’une liste avec quelque chose comme prod([1,2,3,4]).

Ah tiens, ça ne marche pas ! Python3 possède une fonction sum mais pas de fonction prod ? Et bien oui, à l’instar de Scratch qui sait augmenter un accumulateur d’une certaine quantité mais pas multiplier un accumulateur par une certaine quantité, Python même en version 3, ne possède pas de fonction prod appliquée à une liste de nombres, qu’on se le dise [3] !

Ceci dit, la fonction prod, on peut la programmer en réduisant la liste par la fonction qui, à deux nombres, associe leur produit (fonction mult ci-dessous) :

  1. def mult(a,b):
  2.         return a*b
  3. def prod(L):
  4.         return reduce(mult,L)

Télécharger

Listes

Les attendus du programme sont les suivants :

  • générer une liste (en extension, par ajouts successifs, en compréhension) ;
  • manipuler des éléments d’une liste (ajouter, supprimer ... ) et leurs indices ;
  • itérer sur les éléments d’une liste.

En plus, d’autres attendus sont cités sur les fichiers :

  • traiter un fichier contenant des données réelles pour en extraire de l’information et l’analyser ;
  • réaliser un tableau croisé de données sur deux critères à partir de données brutes.

Génération

Pour comparer les approches, on va les utiliser sur un même problème : On souhaite avoir une liste des puissances de 2 depuis 1=20 jusqu’à 256=28

en extension

Fabrication d’une liste

SofusPy possède un menu de listes, dans lequel il y a un gabarit pour fabriquer une liste :

Si on choisit ce bloc, on peut y mettre, dans l’ordre de haut en bas, les éléments à lister :

Que faire si on veut plus que 3 nombres dans la liste ? On clique sur l’icône représentant une roue dentée et on voit ceci :

À droite, les trois blocs intitulés « element » représentent les nombres actuellement dans la liste (1, 2 et 4). En attrapant l’unique bloc intitulé « element » à gauche, on peut le faire glisser à la souris pour l’amener en-dessous des autres :

On voit que maintenant il y a de la place pour ajouter un nouveau nombre à la liste. On y met le nombre 8 et en répétant la manœuvre le nombre de fois nécessaire, on peut avoir une construction de la liste :

On constate que sur la gauche du bloc, il y a une corrugation permettant de brancher ce bloc dans un bloc définissant une expression algébrique : La liste est en elle-même une expression algébrique [4], que Python peut par exemple additionner avec une autre liste ou multiplier par 3.

Un clic sur le bouton « éditeur » permet d’avoir cette expression en Python :

[1, 2, 4, 8, 16, 32, 64, 128, 256]

On constate que les listes sont notées entre crochets (en Python tout du moins) et que les éléments de la liste sont séparés par des virgules. Donc si on veut manipuler une liste de flottants, il faut utiliser (comme toujours en Python) le point décimal pour les écrire, et pas la virgule, puisque celle-ci est déjà utilisée pour séparer les éléments de la liste.

Ce procédé de fabrication d’une liste est appelé en extension, ne serait-ce que parce que ça prend de la place pour une liste qui contient beaucoup de nombres [5].

par ajouts successifs

Ajouter un élément (un nombre par exemple) à la fin d’une liste est possible si la liste est une variable [6]. On appelle L cette liste variable, et on l’initialise à la liste vide. On en profite pour créer une autre variable accmul qui servira à calculer les puissances de 2 par accumulation multiplicative :

Version SofusPy

La traduction en Python est instructive :

  1. L = []
  2. accmul = 1
  3. for k in range(0,9):
  4.     L.append(accmul)
  5.     accmul = accmul * 2

Télécharger

On apprend donc que pour ajouter un élément à la fin de la liste L il faut écrire L.append(element) ce qui résume de facto un dialogue entre l’utilisateur et L :

  • Hé, L !
    • Oui ?
  • Ajoute-toi un element s’il te plaît !
    • OK

En effet append décrit en anglais l’opération d’accrocher une caravane derrière une voiture.

Version pseudocode

L ← []
accmul ← 1
pour k allant de 0 à 8
   insérer la valeur de accmul à la fin de L
   accmul ← accmul × 2

avec une seule variable

On n’a pas vraiment besoin d’un accumulateur [7] pour cette activité puisque la suite ainsi calculée est géométrique et que pour les suites géométriques il existe une expression explicite :

Le script Python produit est aussi instructif, puisqu’il permet de se rappeler comment l’élévation à une puissance est notée en Python :

  1. L = []
  2. for k in range(0,9):
  3.     L.append(2 ** k)

Télécharger

en compréhension

On peut décrire la liste voulue comme « la liste des puissances de 2 » ou « la liste des 2k pour k allant de 0 à 8 ». Cette dernière version se traduit en Python par l’expression suivante :

[2**k for k in range(0,9)]

Cette simplicité tend à faire préférer les listes en compréhension aux autres formalismes, d’autant que comme il s’agit de simples expressions à évaluer, on peut les afficher dans la console interactive :

Manipulation

Lecture

Un être humain sait, à l’œil nu, que la troisième puissance de 2 est 4, ça se lit sur la liste L de l’onglet ci-contre. Mais qu’en est-il de Python ?

Le bloc suivant

est traduit par SofusPy en l’expression L[2].

Pourquoi ? Parce que dans Blockly (ou Sofus) le premier élément d’une liste est le numéro 1 alors qu’en Python le premier élément d’une liste est le numéro 0. Cela induit un décalage auquel il faut systématiquement penser lorsqu’on programme en Python. Ceci dit, avec l’utilisation de range en 2nde, les élèves devraient être habitués à ce que Python, contrairement aux êtres humains, compte à partir de 0 et non de 1 [8].

Suppression

Le bloc suivant

se traduit en Python par l’instruction L.pop(2).

On comprend d’où vient le 2 au lieu du 3, mais pour le reste il faut peut-être des explications : « pop » est le bruit que fait un bouchon de champagne au moment où on le retire [9]. Pour l’explication de ce qui est avant le pop, voir l’onglet précédent (et remplacer « ajouter » par « enlever »).

Variante

Mais en paramétrant le bloc comprenant « supprimer » on découvre qu’il y a une variante que voici :

lequel, une fois traduit en Python, produit exactement le même code que « supprimer » : L.pop(2). Comment expliquer cela ?

En fait, un examen attentif montre que la forme de ce bloc n’est pas exactement la même que celle du bloc précédent : Il y a une corrugation à gauche qui montre que ce bloc est en réalité une expression [10]. Si on place ce genre d’expression dans un print (ou si on l’évalue dans la console) on constate que c’est l’élément supprimé (ici 4) qui est le résultat du calcul de L.pop(2).

Cela montre que la simple écriture d’une expression est considérée comme une instruction valide par Python, mais elle ne produit (normalement) rien lorsque Python l’évalue.

Ajout

On a vu dans l’onglet précédent comment ajouter un élément à la fin de la liste. Si on veut insérer en 3e position, un 5, on utilise ce bloc

qui produit l’instruction Python L.insert(2, 5) et transforme la liste L en

  1. [1, 2, 5, 4, 8, 16, 32, 64, 128, 256]

.

Itération

Dans la plupart des langages de programmation, pour afficher tous les éléments d’une liste L, on fait quelque chose comme ceci :

Version Python :

  1. for k in range(0,9):
  2.     print(L[k])

Télécharger

En Python (comme dans certains autres langages) on peut aussi itérer directement sur les éléments de la liste (sans passer par leurs indices) ; ainsi la variante que voici produit le même effet :

Voici la traduction Python :

  1. for p in L:
  2.     print(p)

Télécharger

En fait, les deux versions peuvent montrer leur utilité : La seconde est idéale s’il s’agit de trouver le minimum des éléments de la liste. La première est indispensable si on veut savoir où est le minimum (ou si on veut connaître les deux, la position et la valeur du minimum). Ceci dit, Python possède une fonction min(L) qui évalue le minimum de la liste L.

Fichiers

Comme exemple, on a choisi les données du ministère de l’éducation nationale sur les écoles et collèges équipés en numérique. Les données ont été filtrées un peu pour ne garder que 3 colonnes :

  1. l’identifiant de l’école ou du collège
  2. le type d’établissement (école d’application, élémentaire, maternelle ou collège)
  3. l’académie abritant l’établissement

Le résultat se trouve dans le fichier que voici, au format csv :

On peut l’ouvrir avec un tableur mais aussi avec Python, grâce au module csv, dont on commence par importer les fonctions (surtout reader qui permet de lire le fichier csv en sachant que c’est un csv) :

  1. from csv import *
  2. outremer = ["","GUYANE","MARTINIQUE","MAYOTTE","LA REUNION","GUADELOUPE","POLYNESIE FRANCAISE"]
  3. ecm = ["Ecole maternelle"]+6*[0]
  4. eel = ["Ecole élémentaire"]+6*[0]
  5. eea = ["Ecole élémentaire d'application"]+6*[0]
  6. col = ["Collège"]+6*[0]

Télécharger

les listes définies avant même l’ouverture du fichier sont celles que l’on affichera dans le tableau croisé à la fin :

  • la liste outremer comprend une entrée vide (la première cellule d’un tableau croisé l’est toujours) puis les noms des départements d’outremer.
  • la liste ecm concerne les écoles maternelles : Elle commence par le nom « Ecole maternelle » puis des nombres actuellement nuls (chacune de ses cellules est en fait un compteur)
  • la liste eel fait pareil pour les écoles élémentaires
  • la liste eea fait pareil pour les écoles d’application
  • la liste col correspond aux collèges (il n’y a pas d’autres catégories d’établissements numériques outre-mer, sauf le lycée de Saint-Pierre et Miquelon)

Comme il y a 6 académies d’outre-mer, on a rajouté 6 fois le nombre 0 dans chaque liste, avec le symbole d’addition qui ajoute le tableau de 0 à la liste comprenant le type de l’établissement scolaire.

Toute la suite s’effectue après l’instruction with qui garantit qu’on ne fait rien si l’ouverture du fichier échoue (par exemple si le fichier Python et le fichier csv ne sont pas dans le même dossier). L’objet tableau est un reader (un lecteur capable de lire le fichier en tenant compte du format « comma separated value » ; on précise quand même que c’est la virgule « comma » qui a été choisie comme séparateur). On peut ensuite itérer sur ce reader. Pour chaque ligne,

  • on ne fait rien si le nom de l’académie n’est pas dans la liste outremer. Si on est bien en outremer,
  • on boucle sur les indices k possibles entre 1 et 6 (ceux qui donnent une académie d’outremer) ; dans cette boucle,
  • on ne fait rien si on est dans la mauvaise colonne. Si on est dans la bonne académie, on sait qu’elle est à l’indice k dans la liste des académies d’outremer, alors pour cette valeur de k :
  • si l’établissement est une école maternelle alors on incrémente le compteur correspondant à l’académie d’indice k parmi les écoles maternelles ;
  • idem pour les autres catégories d’établissements numériques possibles :
  1. with open("ecn.csv") as fichier:
  2.     tableau = reader(fichier,delimiter=",")
  3.     for ligne in tableau:
  4.         if ligne[2] in outremer:
  5.             for k in range(1,7):
  6.                 if ligne[2]==outremer[k]:
  7.                     if ligne[1]=="Ecole maternelle":
  8.                         ecm[k] += 1
  9.                     elif ligne[1]=="Ecole élémentaire":
  10.                         eel[k] += 1
  11.                     elif ligne[1]=="Ecole élémentaire d'application":
  12.                         eea[k] += 1
  13.                     else:
  14.                         col[k] += 1
  15.     print(outremer)
  16.     print(ecm)
  17.     print(eel)
  18.     print(eea)
  19.     print(col)

Télécharger

Cela donne ce tableau croisé :

’’ ’GUYANE’ ’MARTINIQUE’ ’MAYOTTE’ ’LA REUNION’ ’GUADELOUPE’ ’POLYNESIE FRANCAISE’
’Ecole maternelle’ 0 4 0 1 0 0
’Ecole élémentaire’ 19 20 15 58 37 3
« Ecole élémentaire d’application » 0 1 0 0 0 0
’Collège’ 35 8 21 54 34 9

En voici la version csv pour faire une étude sur la numérisation des établissements scolaires en outremer, avec un tableur :

Première

Algorithmes

Suites

  • Calculer un terme de rang donné d’une suite, une somme finie de termes.
  • Déterminer une liste de termes d’une suite et les représenter.
  • Déterminer le rang à partir duquel les termes d’une suite sont supérieurs ou inférieurs à un seuil donné, ou aux termes de même rang d’une autre suite.

Fonctions

  • Calculer une valeur approchée d’une solution d’une équation par balayage.

Statistiques et probabilités

  • À partir de deux listes représentant deux caractères d’individus, déterminer un sous-ensemble d’individus répondant à un critère (filtre, utilisation des ET, OU, NON).
  • Dresser le tableau croisé de deux variables catégorielles à partir du fichier des individus et calculer des fréquences conditionnelles ou marginales.

Variables aléatoires

  • Simuler des échantillons de taille n d’une loi de Bernoulli à partir d’un générateur de nombres aléatoires entre 0 et 1.
  • Représenter par un histogramme ou par un nuage de points les fréquences observées des 1 dans N échantillons de taille n d’une loi de Bernoulli.
  • Compter le nombre de valeurs situées dans un intervalle de la forme [p-ks ;p+ks] pour k ∈ {1;2;3}

Suites

Calculer un terme de rang donné d’une suite, une somme finie de termes

Pour calculer un terme de rang donné d’une suite, l’algorithme dépend de la défintion (explicite ou récurrente) de la suite.

Par exemple, pour la suite arithmétique un=3n+2 de premier terme 2 et de raison 3, on peut définir la suite par une fonction de Python :

Version Blockly

Comme la forme est explicite, il suffit en fait de définir une fonction qui, à un indice n, associe son triple augmenté de 2.

Pour cela, on va chercher dans le menu des fonctions (lequel s’appelle « sous-programmes » ) le bloc qui sert à définir une fonction, on appelle u cette fonction et n sa variable :

On a décoché la case « autoriser les ordres » car il n’y a pas d’instructions à donner dans le corps de la fonction, juste une expression à renvoyer. On fabrique cette expression à l’aide des blocs du menu maths (opérations et constantes) et le bloc n issu des variables :

Désormais la suite un est disponible dans le menu des sous-programmes :

On voit que ce bloc représente une expression à la quelle il faut fournir (par branchement dans la prise à droite) une valeur de n. Ce qui répond au problème. Par exemple pour connaître le 6e terme de la suite, on construit cette expression :

La traduction en Python (obtenue en cliquant sur le bouton « éditeur » donne ceci :

  1. def u(n):
  2.     return 3 * n + 2

Télécharger

Et pour connaître le 6e terme de cette suite on fait u(5).

Si la suite est récurrente par contre il faut deux variables supplémentaires, un compteur k allant de 1 à n et un accumulateur. Par exemple avec la suite vn=1,5×1,1n de premier terme 1,5 et de raison 1,1 :

Version Blockly

Ici l’accumulateur est de type multiplicatif pour une suite géométrique. On initialise l’accumulateur accmul à la valeur 1,5 puis on le multiplie répétitivement par 1,1 :

Pour connaître le 6e terme v5, on fournit la valeur n=5 au bloc qu’on vient de créer :

En Python cela donne :

  1. def v(n):
  2.     accmul = 1.5
  3.     for k in range(1,n + 1):
  4.         accmul = accmul * 1.1
  5.     return accmul

Télécharger

et c’est l’expression v(5) qui donne le 6e terme de cette suite .

pseudocode :

algorithme v(n)
   accmul ← 1,5
   pour k allant de 1 à n
       accmul ← accmul × 1,1
   renvoyer accmul

Pour la somme de n termes de type uk on utilise comme d’habitude un accumulateur :

Version Blockly

On en fait une fonction, admettant comme variable le nombre ntermes de termes à additionner (on additionne donc les termes de rang 0 à ntermes-1) :

  1. def Somme_de_u(ntermes):
  2.     accumulateur = 0
  3.     for k in range(0,ntermes ):
  4.         accumulateur = accumulateur + u(k)
  5.     return accmul

Télécharger

pseudocode

algorithme Somme_de_u(ntermes)
   accumulateur ← 0
   pour k allant de 0 à ntermes-1
       accumulateur ← accumulateur + u(k)
   renvoyer accmul

Simplification

Pour calculer la somme des 20 premiers termes de un, on peut constituer la liste des 20 premiers termes puis demander à Python d’additionner les éléments de cette liste :

sum([u(k) for k in range(20)])

Déterminer une liste de termes d’une suite et les représenter

Si la suite est explicite on privilégie la définition en compréhension :

[u(n) for n in range(20)]

voire

[3*n+2 for n in range(20)]

Pour une suite récurrente par contre on procède par ajouts successifs :

  1. L = []
  2. accmul = 1.5
  3. for k in range(20):
  4.         L.append(accmul)
  5.         accmul = accmul * 1.1

Télécharger

La version en compréhension peut aussi être utilisée si on a défini v(n) comme une fonction comme on l’a fait ci-dessus, mais le calcul sera plus long.

Pour représenter graphiquement une suite vn, on place dans un repère des points de coordonnées k et v(k). Il est d’usage de faire cela avec matplotlib (en lui fournissant la liste des indices et la liste extraite de la suite) mais on peut faire plus court, avec la calculatrice Numworks.

Numworks

La manière la plus concise de faire cela est de dessiner sur la Numworks des petits carrés de largeur 3 aux abcisses 10×k et int(200-10×uk) :

Voici le détail :

  1. from kandinsky import *
  2. noir = color(0,0,0)
  3. for k in range(20):
  4.     fill_rect(10*k, 200-int(10*v(k)), 3, 3, noir)

Télécharger

et l’effet obtenu :

Toutefois la représentation graphique d’une suite est quelque chose que sait faire l’application dédiée de la calculatrice. Par exemple voici la représentation des deux suites un et vn :

Déterminer le rang à partir duquel les termes d’une suite sont supérieurs ou inférieurs à un seuil donné, ou aux termes de même rang d’une autre suite

Sur le graphique ci-dessus il est évident que vk est toujours inférieur à uk. En fait il faut se méfier de ce genre d’évidence puisqu’un théorème d’algorithmique dit que si une suite géométrique est croissante, elle finira par dépasser n’importe quelle suite arithmétique. Pour savoir quand cela va arriver, on va une fois de plus utiliser un compteur, représentant le rang cherché, et on va lui faire compter le nombre de tests de comparaison entre vrang et urang :

version Blockly

En Python cela donne :

  1. rang = 0
  2. while v(rang) < u(rang):
  3.     rang = rang + 1
  4. print(rang)

Télécharger

Avec un seuil

Il suffit de remplacer le second membre de l’inégalité par le seuil :

En Python cela donne

  1. rang = 0
  2. while v(rang) < seuil:
  3.     rang = rang + 1
  4. print(rang)

Télécharger

Fonctions

Calculer une valeur approchée d’une solution d’une équation par balayage

La question évoquée dans la partie sur les accumulateurs multiplicatifs n’a pas encore trouvé de réponse : D’où viennent ces fameux 6 pourcents ?

En fait, pour des raisons psycho-acoustiques, le rapport entre les intervalles entre frettes doit être non seulement le même d’une case (entre deux frettes) à l’autre, mais doit valoir 2, toutes les 12 frettes. Cela est dû à ce que l’octave (rapport 2) est découpé en 12 demi-tons.

On cherche à trouver la raison r d’une suite géométrique vérifiant r12=2. On peut rapidement estimer cette raison par ces constatations :

  • 112=1 donc r est supérieur à 1 ;
  • 212=4096 donc r est largement inférieur à 2 ;
  • 1,112≈3,138 donc r est quelque part entre 1 et 1,1.

D’ailleurs on a vu que r est assez proche de 1,06.

Pour calculer r à 0,001 près on va encore une fois utiliser un accumulateur, mais cette fois-ci on ne l’augmente que de 0,001 à chaque étape :

SofusPy traduit ce script en Python par un simple clic sur le bouton « éditeur » :

  1. accumulateur = 1
  2. while accumulateur ** 12 < 2:
  3.     accumulateur = accumulateur + 0.001
  4. print(accumulateur)

Télécharger

L’exécution du script donne la valeur 1.06 qui correspond bien à la valeur connue des luthiers.

Et le clic sur le bouton « pseudocode » fournit le pseudocode que voici :

accumulateur ← 1
Tant que accumulateur ^ 12 < 2
   accumulateur ← accumulateur + 0.001

Stats

À partir de deux listes représentant deux caractères d’individus, déterminer un sous-ensemble d’individus répondant à un critère (filtre, utilisation des ET, OU, NON)

Voir la partie sur les fichiers dans l’introduction : On a une liste d’établissements scolaires dont la colonne 2 donne le type d’établissement et la colonne 3 donne l’académie où est situé l’établissement.

En appliquant la fonction list au reader, on convertit celui-ci en une liste, donc on peut extraire des sous-listes par compréhension. La difficulté supplémentaire est qu’on a alors une liste de listes. Pour atténuer cette difficulté on va itérer sur les éléments de la liste et non leurs indices.

  • Si on veut connaître les écoles maternelles numériques, on fait
  1. from csv import *
  2. with open("ecn.csv") as fichier:
  3.     T = list(reader(fichier,delimiter=","))
  4.     print([L for L in T if L[1]=="Ecole maternelle"])

Télécharger

(on fait la liste des lignes L de T pour lesquelles le second élément est « Ecole maternelle »)

  • Si on veut connaître les écoles maternelles de l’académie de Dijon, on fait
  1. from csv import *
  2. with open("ecn.csv") as fichier:
  3.     T = list(reader(fichier,delimiter=","))
  4.     print([L for L in T if L[1]=="Ecole maternelle" and L[2]=="DIJON"])

Télécharger

(la traduction de ET en Python est and)

  • Si on veut connaître les écoles maternelles qui ne sont pas dans l’académie de Dijon, on fait
  1. from csv import *
  2. with open("ecn.csv") as fichier:
  3.     T = list(reader(fichier,delimiter=","))
  4.     print([L for L in T if L[1]=="Ecole maternelle" and not L[2]=="DIJON"])

Télécharger

(la traduction de NON en Python est not)

  • Si on veut connaître les établissements scolaires qui sont des écoles maternelles ou qui sont en Martinique, on fait
  1. from csv import *
  2. with open("ecn.csv") as fichier:
  3.     T = list(reader(fichier,delimiter=","))
  4.     print([L for L in T if L[1]=="Ecole maternelle" or L[2]=="MARTINIQUE"])

Télécharger

(la traduction de OU en Python est or)

Remarque

L’application de la fonction len à ces listes permet de savoir qu’il y a

  • 75 établissements qui sont des écoles maternelles ou situés en Martinique ;
  • 4 écoles maternelles en Martinique ;
  • 33 établissements scolaires en Martinique ;
  • 46 écoles maternelles.

Or 46+33=79 et 75+4=79 aussi ce qui illustre le cours.

Dresser le tableau croisé de deux variables catégorielles à partir du fichier des individus et calculer des fréquences conditionnelles ou marginales

On a vu dans les capacités sur les fichiers comment a été établi le tableau croisé des établissements numériques en outremer.

Comme il y a 33 établissements en Martinique, dont 4 sont des écoles maternelles, la fréquence conditionnelle des écoles maternelles parmi les établissements martiniquais est 4/33 soit environ 12% alors que comme il y a au total 5 écoles maternelles numériques outremer, la fréquence conditionnelle des écoles martiniquaises parmi les écoles maternelle est 4/5 soit 80%. Python n’est pas vraiment nécessaire pour cette étape.

Pour calculer les fréquences marginales, on commence par calculer les totaux par ligne, et on les « appende » à la fin de chaque ligne. Pour cela on ajoute à la fin du script de la partie « capacités » les lignes suivantes :

  1.     ecm.append(sum([ecm[k] for k in range(1,7)]))
  2.     eel.append(sum([eel[k] for k in range(1,7)]))
  3.     eea.append(sum([eea[k] for k in range(1,7)]))
  4.     col.append(sum([col[k] for k in range(1,7)]))

Télécharger

académies GUYANE MARTINIQUE MAYOTTE LA REUNION GUADELOUPE POLYNESIE FRANCAISE Total Etablissement
Ecole maternelle 0 4 0 1 0 0 5
Ecole élémentaire 19 20 15 58 37 3 152
Ecole d’application 0 1 0 0 0 0 1
Collège 35 8 21 54 34 9 161
Total académie 54 33 36 113 71 12 319

Le total des totaux est 319 et il suffit de modifier les lignes précédentes pour avoir les fréquences : On divise par 319 (et on multiplie par 100 pour avoir un pourcentage) :

  1.     ecm.append(sum([ecm[k] for k in range(1,7)])/3.19)
  2.     eel.append(sum([eel[k] for k in range(1,7)])/3.19)
  3.     eea.append(sum([eea[k] for k in range(1,7)])/3.19)
  4.     col.append(sum([col[k] for k in range(1,7)])/3.19)

Télécharger

On apprend alors que parmi les établissements scolaires numériques en outremer, il y a environ 1,6% qui sont des écoles maternelles, 47,6% qui sont des écoles élémentaires, 0,3% qui sont des écoles d’application et 50,5% qui sont des collèges.

Probas

Simuler des échantillons de taille n d’une loi de Bernoulli à partir d’un générateur de nombres aléatoires entre 0 et 1

On a vu en début d’article comment simuler une variable de Bernoulli de paramètre p. Pour cela on a défini une fonction B(p) et il suffit de l’utiliser dans une liste en compréhension pour avoir un échantillon de taille n :

  1. def ech(n,p):
  2.     return [B(p) for k in range(n)]

Télécharger

Représenter par un histogramme ou par un nuage de points les fréquences observées des 1 dans N échantillons de taille n d’une loi de Bernoulli

Avec la Numworks, on définit une couleur bleue et un fait un comptage en considérant la liste L comme une liste de compteurs :

Rappels

On écrit ce qui a déjà été vu, en plus de ce qui est spécifique à la Numworks :

  1. from random import *
  2. from kandinsky import *
  3. bleu = color(0,0,255)
  4. def B(p):
  5.     if random()<p:
  6.         return 1
  7.     else:
  8.         return 0
  9. def ech(n,p):
  10.     return [B(p) for k in range(n)]

Télécharger

Puis on fait le décompte des fréquences de succès, afin de connaître la hauteur des rectangles de l’histogramme :

  1. def histo(N,n,p):
  2.     L =[0]*(n+1)
  3.     for k in range(N):
  4.         ns = ech(n,p).count(1)
  5.         L[ns] = L[ns] + 1
  6.     for k in range(n+1):
  7.         fill_rect(2*k,200-L[k],2,L[k],bleu)

Télécharger

Un appel à histo(1000,200,0.36) donne ce genre d’affichage :

Compter le nombre de valeurs situées dans un intervalle de la forme [p-ks ;p+ks] pour k ∈ {1;2;3}

Pour compter le nombre de valeurs situées dans un intervalle, on utilise ... un compteur !

Rappels

On commence par reprendre ce qui avait été vu en 2nde et au début de cet article :

  1. from random import *
  2.  
  3. def racine(x):
  4.         return x**0.5
  5. def moyenne(liste):
  6.     return sum(liste)/len(liste)
  7. def variance(liste):
  8.     liste_des_carres = [x**2 for x in liste]
  9.     return moyenne(liste_des_carres)-moyenne(liste)**2
  10. def ecart_type(liste):
  11.     return racine(variance(liste))
  12. def B(p):
  13.     if random() < p:
  14.         X = 1
  15.     else:
  16.         X = 0
  17.     return X
  18. def ech(n,p):
  19.     return [B(p) for k in range(n)]

Télécharger

Pour compter les 1 dans les échantillons, on fait faire le travail par Python, avec

  1. L = [ech(80,0.36).count(1)/80 for k in range(200)]
  2. s = ecart_type(L)

Télécharger

On en a profité pour calculer l’écart-type s. Et on a fait une liste des fréquences de 1, pas des effectifs, puisque ce sont les fréquences qu’on va comparer avec les nombres p-ks et p+ks.

Le script suivant affiche les fréquences de succés (appartenance à l’intervalle souhaité) :

  1. accumulateur = 0
  2. for ns in L:
  3.         if 0.36-2*s <= ns <= 0.36+2*s:
  4.                 accumulateur = accumulateur + 1
  5. print(accumulateur/200)

Télécharger

En remplaçant les 2 par des 1 ou des 3 on a la réponse.

Terminale

algorithmes

Suites

  • Écrire en langage Python une fonction qui calcule la somme des n premiers carrés, des n premiers cubes ou des n premiers inverses ; établir le lien entre l’écriture de la somme à l’aide du symbole Σ, et les composantes de l’algorithme (initialisation, sortie de boucle, accumulateur, compteur).

Fonctions

  • Intercaler entre deux points déjà construits un troisième point ayant pour abscisse (resp. pour ordonnée) la moyenne arithmétique (resp. géométrique) des abscisses (resp. des ordonnées) des deux points initiaux.

Séries statistiques à deux variables quantitatives

  • Automatiser le calcul de Σi(yi-(axi+b))².
  • Rechercher un couple (a,b) minimisant cette expression parmi un ensemble fini de couples proposés par les élèves ou générés par balayage, tirage aléatoire ...

Variables aléatoires discrètes finies

  • Générer un triangle de Pascal de taille n donnée.
  • Représenter par un diagramme en bâtons la loi de probabilité d’une loi binomiale (n,p). Faire le lien avec l’histogramme des fréquences observées des 1 lors de la simulation de N échantillons de taille n d’une loi de Bernoulli de paramètre p faite en classe de première.
  • Calculer l’espérance Σxipi d’une variable aléatoire suivant une loi de probabilité donnée ; cas particulier d’une variable aléatoire suivant la loi binomiale B(n,p).
  • Représenter graphiquement l’espérance de lois binomiales B(n,p) à p fixé et n variable, à n fixé et p variable puis faire le lien avec l’expression admise de l’espérance.

Suites

Écrire en langage Python une fonction qui calcule la somme des n premiers carrés, des n premiers cubes ou des n premiers inverses ; établir le lien entre l’écriture de la somme à l’aide du symbole Σ, et les composantes de l’algorithme (initialisation, sortie de boucle, accumulateur, compteur)

Somme des carrés

Pour additionner les termes d’une suite, on utilise un accumulateur. Et comme il s’agit d’une suite, on utilise un compteur k. Et ce sont les valeurs de k² qui vont être accumulées.

Version Blockly

On définit une fonction Sigma2 pour rappeler qu’il s’agit de la somme des carrés (des k²) dans laquelle on additionne les carrés des valeurs du compteur pour avoir la somme des carrés dans l’accumulateur :

Traduit en Python cela donne cette fonction :

  1. def Sigma2(n):
  2.     compteur = 1
  3.     accumulateur = 0
  4.     while compteur <= n:
  5.         accumulateur = accumulateur + compteur ** 2
  6.         compteur = compteur + 1
  7.     return accumulateur

Télécharger

Une fonction d’argument entier naturel (n supposé non nul puisque 0²=0 et on ne change pas la somme en ajoutant 0) est en fait une suite. Elle possède d’ailleurs une expression explicite [11].

pseudocode

La version pseudocode donnée par SofusPy :

algorithme Σ2(n)
   compteur ← 1
   accumulateur ← 0
   Tant que compteur ≤ n
       accumulateur ← accumulateur + compteur²
       compteur ← compteur + 1
   renvoyer accumulateur

La notation Σ est classique pour désigner une expression obtenue en sommant d’autres expressions. Et il est d’usage (même en Python) lorsqu’il n’y a qu’un seul compteur, de l’appeler k. La notation complète implique le compteur (en bleu), son initialisation (en vert) et la condition de sortie de la boucle (en rouge) :

La lettre Σ désigne alors l’accumulateur, et le k² ce qu’on accumule.

Somme des cubes

Pas de grand changement, il suffit de remplacer l’exposant 2 par un exposant 3 :

  1. def Sigma3(n):
  2.     k = 1
  3.     S = 0
  4.     while k <= n:
  5.         S = S + 1 / k
  6.         k = k + 1
  7.     return S

Télécharger

Variante

Le range de Python est capable de gérer le compteur k tout seul :

  1. def Sigma3(n):
  2.     S = 0
  3.     for k in range(1,n+1):
  4.         S = S + 1 / k
  5.     return S

Télécharger

Somme des inverses

  1. def H(n):
  2.     compteur = 1
  3.     accumulateur = 0
  4.     while compteur <= n:
  5.         accumulateur = accumulateur + 1 / compteur
  6.         compteur = compteur + 1
  7.     return accumulateur

Télécharger

Le nom Hn donné à cette fonction vient de ce que la suite s’appelle série harmonique. Leonhard Euler a étudié cette suite au 18e siècle et lui a trouvé une allure logarithmique.

Fonctions

Intercaler entre deux points déjà construits un troisième point ayant pour abscisse (resp. pour ordonnée) la moyenne arithmétique (resp. géométrique) des abscisses (resp. des ordonnées) des deux points initiaux

La moyenne arithmétique est en fait une fonction, qui, à deux nombres a et b, associe la moitié de leur somme. On peut donc faire comme en 2nde et programmer cette fonction en Python :

  1. from math import *
  2.  
  3. def moyarith(a,b):
  4.         return (a+b)/2
  5. def moygeom(a,b):
  6.         return sqrt(a*b)

Télécharger

On en profite pour programmer aussi la fonction donnant la moyenne géométrique. En assimilant un point à une liste de deux nombres, la fonction insert de Python permet d’insérer le nouveau point, ou tout au moins de le calculer :

  1. def nouveau_point(A,B):
  2.     return [moyarith(A[0],B[0]) , moygeom(A[1],B[1])]

Télécharger

Mais ici on fait le choix de ne pas considérer deux points mais une liste de deux abscisses et une liste de deux ordonnées. La fonction Python va insérer la moyenne arithmétique dans la liste X des abscisses et la moyenne géométrique dans la liste des ordonnées :

  1. def insertion(X,Y):
  2.         X.insert(1,moyarith(X[0],X[1]))
  3.         Y.insert(1,moygeom(Y[0],Y[1]))

Télécharger

Avec

  1. X = [0,1]
  2. Y = [1,2]

Télécharger

au départ, on obtient après l’exécution de cette fonction

  1. X == [0,0.5,1]
  2. Y == [1,1.41421356237,2]

Télécharger

On gagne deux choses avec ce point de vue :

  • On peut représenter graphiquement les deux listes X et Y dans matplotlib.pyplot ;
  • On peut recommencer à insérer des points de ce genre dans les listes X et Y ce qui améliore la qualité de la représentation, et laisse voir qu’on définit ainsi une fonction :
  1. def insertion(X,Y):
  2.         k = 0
  3.         while k<len(X)-1:
  4.                 X.insert(k+1,moyarith(X[k],X[k+1]))
  5.                 Y.insert(k+1,moygeom(Y[k],Y[k+1]))
  6.                 k = k+2

Télécharger

Avec from matplotlib.pyplot import * les deux lignes

  1. plot(X,Y)
  2. show()

Télécharger

donnent ce graphique :

qui représente la fonction 2x.

Remarque : Avec 10 à la place de 2 dans la liste Y au début, John Napier a créé au début du 17e siècle d’une manière similaire la fonction 10x et l’a inversée pour obtenir le logarithme décimal.

Stats

Automatiser le calcul de Σi(yi-(axi+b))²

Bien entendu, où il y a une somme, il y a un accumulateur. Pour faire un peu plus court on va l’appeler S.

Version Blockly

On suppose qu’on a deux listes X et Y :

Blockly permet de représenter indifférement en ligne ou sous forme d’un arbre sytaxique une expression un peu complexe :

Cela donne, en Python, cette fonction :

  1. def somme2(a, b):
  2.     S = 0
  3.     for k in range(0,4):
  4.         S = S + (Y[k] - (a * X[k] + b)) ** 2
  5.     return S

Télécharger

On va chercher à minimiser cette fonction avec les listes suivantes :

  1. X = [2, 5, 13, 34]
  2. Y = [1, 3, 8, 21]

Télécharger

Rechercher un couple (a,b) minimisant cette expression parmi un ensemble fini de couples proposés par les élèves ou générés par balayage, tirage aléatoire ...

On va engendrer des couples (ar,br) au hasard et ne garder que ceux qui ont donné une valeur de m plus petite que la valeur actuelle (m est l’image de (ar,br) par la fonction précédente) Ceci revient à utiliser pour m une sort d’accumulateur mais au lieu de l’addition ou la multiplication, on prend l’opération qui à deux nombres, associe le plus petit des deux.

  1. am = 0
  2. bm = 0
  3. m = somme2(am, bm)
  4. for compteur in range(0,10001):
  5.     (ar,br) = (random(),random())
  6.     if somme2(ar, br) < m:
  7.         m = somme2(ar, br)
  8.         am = ar
  9.         bm = br

Télécharger

Il faut de nombreuses itérations pour stabilisation de l’algorithme mais on peut tenter de deviner (ou lire graphiquement) les coordonnées optimales.

Probas

Générer un triangle de Pascal de taille n donnée

On va faire une liste de listes : Chacune de ces listes représente une ligne du triangle de Pascal. On initialise cette liste avec la liste correspondant à la première ligne du triangle de Pascal, à la ligne 1 (on rajoute un 0 à la fin de chaque ligne pour simplifier un peu le code Python) : Il y a une seule manière de choisir 0 élément parmi 0, et aucune manière de choisir 1 élément parmi 0. La ligne 3 est la boucle sur les lignes du tableau :

  1. def coeff_binomiaux(n):
  2.     triangle = [[1,0]]
  3.     for k in range(1,n+1):
  4.         triangle.append([1]+(k+1)*[0])
  5.         for j in range(1,k+1):
  6.             triangle[k][j]=triangle[k-1][j]+triangle[k-1][j-1]
  7.     return triangle

Télécharger

À la ligne 4 on crée une ligne du triangle de Pascal, remplie de 0 ou presque (le premier coefficient est le nombre de manières de choisir rien parmi n, c’est 1). La ligne 5 est une boucle sur l’élément de la ligne que l’on construit, par la relation de Pascal qui est à la ligne 6.

Représenter par un diagramme en bâtons la loi de probabilité d’une loi binomiale (n,p). Faire le lien avec l’histogramme des fréquences observées des 1 lors de la simulation de N échantillons de taille n d’une loi de Bernoulli de paramètre p faite en classe de première

Pour dessiner, rien de mieux que la calculatrice. Sauf qu’il faut reprogrammer l’algorithme de calcul de la loi binomiale pour éviter la saturation de la mémoire de la calculatrice :

Le résultat est à comparer avec l’« histogramme » vu en 1ère (onglet variables aléatoires) :

Pour comparer

Revoici l’histogramme obtenu en 1ère :

Calculer l’espérance Σxipi d’une variable aléatoire suivant une loi de probabilité donnée ; cas particulier d’une variable aléatoire suivant la loi binomiale B(n,p)

Calcul

L’activité précédente a été l’occasion d’utiliser cet algorithme rapide de calcul de la loi binomiale :

  1. def B(n,p,k):
  2.     q = 1
  3.     for j in range(k):
  4.         q = q*p*(n-j)/(k-j)
  5.     q = q*(1-p)**(n-k)
  6.     return q

Télécharger

L’expression [B(20,0.36,k) for k in range(21)] donne alors sous la forme d’une liste, la loi binomiale de paramètres 20 et 0,36. On suppose que cette liste est stockée dans une variable appelée loi.

Pour calculer l’espérance, à partir de la loi (donnée sous forme d’une liste), on utilise un accumulateur dans lequel on va sommer les produits du compteur k par la probabilité que X=k :

  1. def E(loi):
  2.     accumulateur = 0
  3.     for k in range(len(loi)):
  4.         accumulateur = accumulateur + k*loi[k]
  5.     return accumulateur

Télécharger

Représenter graphiquement l’espérance de lois binomiales B(n,p) à p fixé et n variable, à n fixé et p variable puis faire le lien avec l’expression admise de l’espérance

Une fois importées les fonctions de matplotlib.pyplot on peut créer deux listes X (les valeurs de n) et Y (les valeurs de l’espérance pour n et 0,36) pui les dessiner :

  1. X = [n for n in range(2,200)]
  2. Y = [E([B(n,0.36,k) for k in range(n+1)]) for n in range(2,200)]
  3.  
  4. plot(X,Y)
  5. show()

Télécharger

qui donne ce graphique montrant que l’espérance est proportionnelle à p :

Et la version suivante :

  1. X = [P for P in range(100)]
  2. Y = [E([B(40,P/100.,k) for k in range(41)]) for P in range(100)]

Télécharger

donne ce graphique (pour n=40) montrant que l’espérance est également proportionnelle à p :