Les types de base: numériques, string, booléens En python, les objets natifs de base ont pour type:
nombre entier: integer ou int en Python nombre réel décimal: float chaine de caractères: str les valeurs logiques: booléen bool Lorsque l’on présente une valeur dans le programme, le langage s’adapte selon le type, comme on le verra plus loin.
Python est-il déjà installé? Verifier si Python est installé sur votre ordinateur:
Vous pouvez vérifier cela en ouvrant l’invite de commandes et en tapant:
python –version Windows: Télécharger le fichier d’installation depuis le site officiel de Python. Lancer l’executable et cocher “Add Python to PATH”. Puis cliquer sur Install now
Linux: Python peut être installé et géré via un gestionnaire de paquets comme apt, yum.
Le module Turtle permet d’avoir un environnement simple muni d’une interface graphique.
La page suivante présente un aide-mémoire avec les principales instructions.
Il est conseillé d’avoir bien lu et traité les exemples des pages:
TP boucles et fonctions Cours sur les fonctions Premiers tracés Script initial Ces exemples utilisent une boucle bornée pour répéter des consignes (for .. in range)
Les exemples suivants montrent le rôle crucial des variables dans les algorithmes…
Compteur de passages
Un dispositif numérique, équipé d’un capteur, compteur le nombre de passage par une porte.
detecteur de passage à capteur infra rouge
L’algorithme utilisé comporte 3 parties:
initialisation de la variable
boucle avec condition d’execution
modification de la variable
Il utilise la fonction: coupure_faisceau
Et la variable: i nombre de passages detectés
i = 0
repeter indefiniment:
{
si coupure_faisceau_lumiere():
{
i = i + 1
fin si
}
fin repeter
}
Point neutre Terre-Lune
Dans l’un de ses célèbres romans intitulé De la Terre à la Lune, Jules Verne (1828-1905) relate les aventures de trois héros ayant pris place à l’intérieur d’un énorme projectile qu’un gigantesque canon, baptisé Colombiad, propulse en direction de la Lune. Lors de ce périple, Jules Verne fait allusion à un point neutre, situé à une distance d = 350 000 km du centre de la Terre où les forces
gravitationnelles exercées par la Terre et la Lune sur le projectile se compensent.
point neutre sur la droite Terre-Lune
L’algorithme utilisé comporte 3 parties:
phase d’initialisation de la variable
boucle avec condition d’execution
modification de la variable
Il utilise les fonctions: F1 force de gravitation de la Terre, F2 force de gravitation de la Lune
Et la variable: d distance à la surface de la Terre
d = 0
repeter tant que F1 (d) > F2(d):
{
d = d + 1
fin repeter
}
afficher d
calculer en python
Les types de base: numériques, string, booléens
En python, les objets natifs de base ont pour type:
nombre entier: integer ou int en Python
nombre réel décimal: float
chaine de caractères: str
les valeurs logiques: booléen bool
Lorsque l’on présente une valeur dans le programme, le langage s’adapte selon le type, comme on le verra plus loin.
Pour vérifier le type d’un objet, on utilise la fonction type
Pour changer le type, on utilise les fonctionsint, float, str. On utilise par exemple int lorsque l’on veut transformer un float ou un str en un entier:
>int('12')12>str(12)'12'>float(12)12.0
Les nombres entiers et décimaux
Entier
Un entier: type int(ou integer). C’est un nombre qui n’a pas de point décimal. Les algorithmes utilisent en général des entiers, ce qui est avantageux pour les opérations de comparaison comme == ou !=.
valeurs possibles: 1, 2492042932330932, -23,...
Certaines opérations retournent un résultat de type entier:
Un entier peut avoir une valeur aussi grande que celle que la machine peut stocker. Pour un nombre entier non signé, stocké sur 32 bits, cette valeur maximale vaut $2^{32}-1$
un nombre entier négatif: type int s’écrit avec un $-$ devant: $-10$ par exemple. Les entiers signés, codés sur 32 bits ont des valeurs qui s’étendent entre $[-2^{31},2^{31}-1]$
Décimal
un nombre décimal: type float s’écrit avec un point comme séparateur, comme par exemple: 6.02
Les nombres exprimés avec l’opérateur e (puissance de 10), sont aussi des float, des décimaux:
>a=12e3# a vaut 12000>print(a)12000.0>type(a)float
La division de 2 nombres avec l’opérateur $/$ retourne toujours un type float, même avec des entiers:
>20/82.5>20/102.0
Les float en Python ont une précision limitée. Ils sont généralement codés sur 15 chiffres significatifs et encodés sur 53 bits. Cela génère des imprecisions comme par exemple:
>0.3/0.12.9999999999999996
Chaine de caractère
C’est une séquence constituée d’un ou plusieurs caractères, entourés de guillemets simples ou doubles.
Notez que des chiffres mis entre guillemets sont des chaines de caractères et ne peuvent pas être manipulés comme des nombres (voir plus loin).
Exemples
"Bonjour"'Hello'"18""Un longue chaine de caractères"'une autre chaine'
caractères spéciaux
Certains caractères spéciaux ne sont pas affichés, mais permettent la mise en forme:
Par exemple, le caractère \n génère un retour à la ligne:
>citation_python='je disais, "être ou ne pas être,\ntelle est la question"'>print(citation_python)# afficheêtreounepasêtre,telleestlaquestion
addition de chaines
L’addition de chaines* (concaténation) se fait avec l’opérateur +
>print("Bonjour"+"Hello")BonjourHello
L’opérateur * permet des répétitions multiples:
>print('Hi'*3)HiHiHi
Ou bien avec des accolades {} dans une expression formatée. Exemples:
# Exemple 1 avec .formatm=100Ec=1200resultat="Pour le systeme m = {} et E = {}".format(m,Ec)print(resultat)# affiche# Pour le systeme m = 100 et E = 1200
# Exemple 2 avec un f-stringm=100Ec=1200resultat=f"Pour le systeme m = {m} et E = {Ec}"print(resultat)# affiche# Pour le systeme m = 100 et E = 1200
L’exemple 2 illustre une chaine particulière appelée f-string. C’est une chaine:
préfixée par un f
suivie par une chaine entre guillemets "" ou ''
contenant des accolades {}
où tout texte placé entre accolades sera remplacé par la valeur de la variable correspondante.
Test d’appartenance
L’opérateur in permet de tester si une suite de caractères se trouve dans un chaine:
"ou" in "jour" vaut True
"ou" not in "jour" vaut False
Ordre lexicographique
On peut comparer les caractères ou les mots à partir de leur rang dans l’alphabet:
Utiliser les opérations booléennes dans un programme
Le booléen permet un branchement dans un algorithme (voir les structures conditionnelles). Exemples:
ifTrue:# instruction 1else:# instruction 2# execution du bloc d'instruction 1ifFalse:# instruction 1else:# instruction 2# execution du bloc d'instruction 2if10>1:# instruction 1else:# instruction 2# execution du bloc d'instruction 1
On peut souhaiter executer infiniment le même bloc d’instructions, avec l’instruction `while:
whileTrue:# bloc d'instructions
Changer de type avec la fonction bool
Lors de la transformation de type avec bool ou int, le True correspond à un 1 et le False à un 0:
>bool(1)True>bool(0)False>int(True)1>int(False)0
Les opérations de base
1. Un langage informatique permet de réaliser des opérations sur des valeurs. L’écriture de ces opérations peut différer de ce que l’on écrit avec la calculatrice. Voici la liste des opérateurs en Python:
opérateur
rôle
équivalent sur une calculatrice
+
addition
$1 + 99$
-
soustraction
$99 - 1$
*
multiplication
$10 \times 10$
/
division
$\tfrac{1}{3}$
//
division entière
pas d’équivalent
%
reste de la division
pas d’équivalent
**
exposant
$2^{4}$
e
puissance de 10 (pour l’écriture en notation scientifique)
$1.2E-3$ ou $1.2\times 10^{-3}$
2. Ces opérateurs peuvent aussi être appliqués sur des chaines de caractères.
opérateur
rôle
exemple
+
concaténation (ajoute les chaines de caractères)
"Aïe" + "Aïe" + "Aïe"
*
multiplication (ajoute plusieurs fois la même chaine, bout à bout
"Aïe" * 3
3. Un nombre ne peut pas être ajouté à une chaine de caractères:
4. Opérations logiques
Une opération logique consiste à comparer 2 valeurs et tester si celles-ci sont égales, ou s’il y a une relation d’ordre entre elles. Le résultat d’une opération logique ne peut être que True ou False:
opérateur
pour tester…
==
l’égalité
!=
l’inégalité (est différent de) !
>
l’ordre supérieur
<
l’ordre inférieur
>=
l’ordre supérieur ou égal
<=
l’ordre inférieur ou égal
ainsi, pour tester l’égalité entre 3 et 1+2, on peut écrire en python:
Remarque: Le test de l’égalité n’est pas adapté pour les nombres réels. Seulement pour les nombres entiers. Ainsi, en Python, l’opération 0.1*3 == 0.3 renvoie … False!
Calcul sur des valeur entières
Les programmes informatiques préfèrent utiliser des valeurs entières pour les calculs, même si les calculs avec nombres à virgules sont possibles. Pour cette raison, les opérateurs // et % sont souvent utilisés en combinaison.
Rappel:La division euclidienne de a par b est définie comme ceci: a est égal au quotient de a//b multiplié par le diviseur b, augmenté du reste a%b:
$$a = (a//b)*b + a%b$$
Usages classiques:
n%2 vaut 0 si n est pair
n%2 vaut 1 si n est impair
n%10 conserve les unités
n//10 conserve les dizaines et supprime les unités.
1. Definition: Une variable sert à stocker une valeur, qui peut être un nombre, une chaine de caractère, ou autres. Une variable est identifiée par un nom, et pointe vers un espace mémoire.
VARIABLE = espace de STOCKAGE
Une variable est donc une zone précise de la mémoire vive de l’ordinateur (on parle d’adresse mémoire). À partir de cet emplacement, on trouvera une succession de bits dont l’agencement spécifique déterminera à la fois une valeur et un type.
2. Quel nom peut-on choisir pour une variable?: On peut choisir une lettre simple, minuscule ou majuscule, ou une chaine de caractères SANS espaces, et commençant obligatoirement par une LETTRE. Le nom peut contenir certains caractères spéciaux comme par exemple _. (ne pas utiliser le signe -, utilisé pour une soustraction entre 2 variables).
Exemples de noms de variables:
x
y
a
B
longueur_L1
nom
age
personne3
Score
Points_de_vie
…
L’idée est de choisir un nom assez explicite, et d’éviter d’utiliser trop souvent x, y, a, b, c, …
3. Affectation On affecte une valeur à une variable en utilisant l’opérateur =.
Par exemple, pour affecter la valeur 5 à la variable x, on fait:
x=5
Pour vérifier la valeur d’une variable, il suffit d’écrire celle-ci:
soit toute seule dans une cellule du notebook
x# retourne 5
soit à la dernière ligne de la cellule du notebook:
x=5# retourne 5
Soit avec la fonction print (ne pas mettre de guillemets)
x=5print(x)# retourne 5
On peut modifier la valeur d’une variable existante. On peut méme lui affecter le résultat d’une opération:
x=12/2x# retourne6.0# remarquer ici que la division simple retourne un float
Et utiliser la valeur de cette même variable pour l’opération:
x=6x=x+1x# retourne7
Affectation multiple: On peut affecter une valeur à plusieurs variables en une seule ligne, ce qui amèliore la lecture d’un script:
a=1b=2
peut être remplacé par:
a,b=1,2
4. Opérations sur les variables
Une variable a un TYPE qui est défini lors de l’affectation. Python s’adapte lorsque vous faites une affectation et choisit le type correspondant.
Pour démarrer, nous verrons les TYPES str (chaine de caractère), int (nombre entier) et float (nombre décimal, en virgule flottante).
Les opérations possibles sur une variable dépendent de son type.
Pour les variables de type nombre int et float, on peut utiliser les opérateurs +,-,*,/,**,//,%
Pour les variables de type str on peut aussi utiliser les opérateurs +,* mais le résultat est différent (opérateurs de concaténation).
Lorsque l’on modifie une variable, on affecte à nouveau à la variable le résultat de l’opération:
x=6x=x+8# x+8 vaut 14 que l'on affecte a nouveau a xprint(x)# affiche 14
Opérateur d’affectation composée. L’instruction x = x + 8 peut être simplifiée en x += 8.
L’opérateur += réalise l’opération et l’affectation à la même varaible, x:
x=6x+=8# x+8 vaut 14 que l'on affecte a nouveau a xprint(x)# affiche 14
Il existe d’autres opérateurs d’affectation composée: -=, *=, /=.
Exemple:
x=6x/=2x# affiche 3.0
5. Variables et paramètres d’une fonction
Les variables déclarées avec la fonction, entre parenthèse sont appelées paramètres. Le schéma suivant illustre l’affectation des valeurs des variables a = x et b = y lors de l’appel de la fonction additionne(x, y):
Visualiseur python
Le site pythontutor permet de visualiser le contenu des variables et leur espace de nom.
exemple 1: un espace mémoire pour chaque variable
x=10y=14x=x+2print(x)
exemple de représentation avec 2 variables x et y dans le main
Cliquer sur l’image pour lancer l’app pythontutor. Cliquer sur next pour dérouler le script pas à pas.
exemple 2: un espace mémoire pour les variables et pour les fonctions
x=10y=14# creation de la fonction avec le mot clé defdefadditionne(a,b):returna+b# appel de la fonction avec a = 10 et b = 14>additionne(x,y)24
exemple avec appel d'une fonction
Cliquer sur l’image pour lancer l’app pythontutor. Cliquer sur next pour dérouler le script pas à pas.
TP3b, algorithmes utilisant boucle while et structures conditionnelles: Lien
Structures conditionnelles simples et avec alternative
Conditions
1. Définition : Une instruction conditionnelle vérifie si une certaine condition est vraie avant d’executer son code :
if instruction_conditionnelle :
code_à_executer
Exemple :
ifprix_essence>1.8:print('Trop cher')
Remarquer que l’instruction if .. condition ..: finit par 2 points :, et que la ligne suivante est indentée
Toute portion de code associée à une structure de contrôle (finissant par 2 points :) nécéssite une indentation.
2. Les blocs du programme
En Python, on utilise l’indentation (le retrait de la ligne) pour rendre compte des blocs de code.
de pybloc au script python
Le bloc de code à executer peut contenir plusieurs lignes, à condition de respecter l’indentation. (2 ou 4 espaces, ou touche TAB).
3. L’alternative if - else
Une instruction if - else contient une instruction if qui s’execute si la condition est True et une clause else qui s’execute si la condition est False.
ifhauteur_plant<3:print('laisser le plant dans la serre')else:print('le mettre dehors')
4. Conditions multiples if - elif - else
Un bloc if - elif - else comprend une premiere instruction if, puis une suite de conditions de tests elif si le premier test echoue, puis un bloc else qui s’execute si tous les autres tests échouent.
Même s’il n’est pas obligatoire, il est fortement recommandé de finir une série de conditions elif par le bloc else.
ifhauteur_plant<3:print('laisser le plant dans la serre')elifhauteur_plant<10:print('le sortir le jour')elifhauteur_plant<15:print('le mettre dehors')else:print('Pret pour la recolte')
Rappelez vous:
elif est toujours suivi d’une condition
else n’est pas suivi d’une condition. C’est l’alternative, dont le bloc est executé lorsqu’aucune des conditions precedentes n’est vraie.
Tests logiques
Il s’agit d’une expression booléenne qui est évaluée est qui renvoie True si elle est vrai, False sinon.
Opérateurs de comparaison
Quelques exemples de tests logiques :
age==18# egalitéage!=18# inegalitéage<=18# inferieur ou egalnom=='John'# egalité de chaines
Opérateurs et combinaisons logiques
L’expression peut aussi contenir les opérateurs logiques de combinaisons: and, or, not.
L’expression suivante, A and B est evaluée à True si A vaut True, et B vaut True. Dans tous les autres cas, (A vaut False, ou B vaut False, ou A et B valent False), A and B est evaluée à False. On peut résumer tous les cas dans une table logique:
A
B
A and B
False
False
False
False
True
False
True
False
False
True
True
True
Pour l’opérateur logique or:
A
B
A or B
False
False
False
False
True
True
True
False
True
True
True
True
et pour l’opérateur not
A
not A
False
True
True
False
Exemple:
n=int(input('entrer un nombre entier: '))ifn%2==0andn>0:print('vous avez entré un entier pair et positif')
Une instruction if peut également tester une valeur booléenne et exécuter son code si cette valeur vaut True, comme par exemple, ci-dessous, avec if jeu_actif:
Il n’est pas nécéssaire d’écrire == True comme ici avec if jeu_actif == True:
ifjeu_actif:print('jouons !')
Test sur une liste
On peut aussi vérifier si un élement existe dans une liste :
capitales=['Paris','Berlin','Rome','Londres','Madrid']'Paris'incapitales# retourne# True car 'Paris' est dans la liste capitales
Test sur un dictionnaire
Le mot-clé in permet de tester si une clé est présente dans le dictonnaire:
dico={'cle1':'val1','cle2':'val2','cle3':'val3'}print('cle1'indico)# affiche Trueprint('val1'indico)# affiche False car `'val1'` est une valeur et non une clé.
Remarque : 0 et None
Dans le test logique, 0 et None se comportent comme s’il s’agissait de False:
ch=input('Entrez un nombre entier quelconque')n=eval(ch)ifn:print("vrai")else:print("faux")
Ce petit script, lorsqu’il est executé, renvoie toujours True quel que soit le nombre saisi, mais False dans les cas suivants. Si on saisit
0 # zero
None # le type Rien
A savoir: dans certains cas, on peut faire l’économie de l’opérateur logique. Dans l’instruction conditionnelle if n, la condition vaut True dès que n est différent de 0 ou de None, ou bien n vaut True.
Ainsi, les scripts suivants sont équivalents
# script 1# sortir = True ou bien sortir = Falseifsortir:print('Vous pouvez sortir')ifsortir==True:print('Vous pouvez sortir')
# script 2# n est un entierifn!=0:print('n est different de 0')ifn:print('n est different de 0')
Boucles non bornées: while
1. Definition: Une boucle non bornée permet de répéter un élément de code un nombre à priori inconnu de fois.
On écrit l’instruction: while <condition d execution>:
Le bloc de code est indenté sous cette première ligne:
while<conditiondexecution>:instruction1instruction2instructionsuivante# suite du programme
Cette boucle repète l’execution d’un bloc de code (instruction 1, instruction 2), tant que la <condition> est evaluée à True. Le test sur la <condition> est réalisé à chaque itération.
Lorsque cette <condition> n’est plus réalisée, le programme passe à l’instruction suivante.
Souvent, il sera nécessaire de démarrer le programme par initier une variable (celle utile pour la condition d’execution). De sorte que cette condition d’execution soit évaluée à True, et que le bloc de cette boucel s’execute au moins une fois.
Exemple 1: Réaliser un compteur
print("Jeu du cache-cache: compte jusqu'à 10")i=1whilei<=10:print(i)i=i+1print("c'est fini, j'arrive")
à la première itération, i vaut 0, donc la condition i <= 10 est évaluée à True et le bloc est executé. Le programme affiche 1 et i finit avec la valeur 2 (i = i + 1)
La boucle se poursuit jusqu’à ce que i soit égal à 11. Alors i <= 10 est évaluée à False et le programme poursuit APRES la boucle, avec la dernière instruction: affiche "c'est fini"
Exemple 2: reste de la division euclidienne de 40 par 3
r=40whiler>=3:r=r-3print('à la fin du programme, r vaut '+str(r))
A la première itération, r vaut 40 donc la <condition> r > 3 est True. r est diminué de 3 et prend la valeur 37.
A la dernière itération, 4 >= 3 est evalué à True. r est diminué de 3 et prend la valeur 1
Puis r >= 3 est evalué à False. Le bloc n’est pas executé et le programme s’arrête s’il n’y a pas d’autres instructions (ou poursuit le script sinon).
2. Le problème de l’arrêt
Pour le script précédent, si l’on avait remplacé la condition r >= 3 par r == 3 le programme aurait pu executer le bloc r = r - 3 indefiniment. r aurait pris successivement les valeurs 40, 37, … 4, 1, -2, -5, … etc, sans jamais prendre la valeur 0.
C’est le problème avec les boucles non bornées. Celles-ci peuvent ne pas finir, ce qui peut bloquer la machine.
Cet effet de boucle infini peut être recherché, par exemple en robotique, où l’on veut que le programme se poursuive indéfiniment. Ainsi, la structure d’un programme python sur carte microbit commence par la structure suivante:
frommicrobitimport*whileTrue:# instructions# ...
Mais dans le cas général, il faudra veiller à ce que la boucle finisse à un moment donné. Par exemple, dans le script suivant, on met l’instruction break qui a pour effet d’interrompre la boucle lorsque break est executée :
whileTrue:# boucle qui à priori ne finit jamaisnom=input('Quel est votre nom ?')ifnom=='quitter':breakprint('Bonjour, {}'.format(nom))print('sortie de la boucle')
Exemple:
Quel est votre nom ? John
Bonjour, John!
Quel est votre nom ? quitter
sortie de la boucle
On peut représenter ce script avec des modules à assembler type scratch ou blocky):
analogie avec des briques de construction du programme
Remarque
Construction de la boucle bornée
Le bloc d’instruction sera executé n fois. Celui-ci peut contenir une ou plusieurs instructions, du moment qu’elles sont bien positionnées dans le bloc.
En Python, le bloc est identifié par une indentation: un retrait par rapport au bord gauche, comprenant 2 espaces (ou 4).
Pour sortir du bloc, on élimine l’indentation (on revient sur le bord gauche)
bloc de retour à la fin de la boucle
La fonction range(n) renvoie la liste des entiers de 0 à n-1. C’est un principe général en informatique, on commence toujours à compter à partir de 0, et il faut donc s’arrêter à n-1 pour effectuer n fois la boucle.
Pour chaque itération, le variant i prend une nouvelle valeur de l’ensemble {0,1,2,... n-1}, et peut être utilisé dans le bloc d’instructions.
On peut choisir n’importe quel nom pour le variant, pas seulement i.
Contrairement à la boucle non bornée while, le programmeur ne s’occupe pas de faire varier i à chaque itération. Cela ce fait tout seul.
Exemple:
foriinrange(2):print(i)# affiche01
La boucle est executée 2 fois, et affiche 0 puis 1. Pas 2.
Boucle bornée et séquence
L’instruction utilisant le mot-clé for suit la construction suivante:
forvariantiniterable:# bloc de code à repeter
Ce que l’on appelle iterable, c’est un ensemble de valeurs que prend successivement le variant.
iterable = range(5)
Dans ce premier cas, le variant prend successivement le valeurs de l’ensemble {0,1,2,3,4}. Le variant vaut 0 lors le premiere itération, puis 1 à la deuxieme, etc …
foriinrange(5):print(i)# affiche01234
A tester vous-même (python): Exemple 1: utiliser la fonction range
iterable = "abc"
Dans ce deuxieme cas, le variant i prend successivement le valeurs de l’ensemble {"a","b","c"}. Le variant vaut “a” lors le premiere itération, puis “b” à la deuxieme, etc …
foriin"abc":print(i)# affiche"a""b""c"
A tester vous-même (python): Exemple 2: utiliser une séquence de type str
iterable = [1998,2018]
Les listes en python sont des sequences qui placent les valeurs entre crochets [...]. Les valeurs sont séparées par des virgules ,
L=[1998,2018]foranneeinL:print('La France a gagné la coupe du monde en ',annee)
A tester vous-même (python): Exemple 3: utiliser une séquence de type list
le variant annee prend successivement le valeurs de l’ensemble {1998,2018}
On peut placer autant de valeurs que l’on souhaite dans une liste.
Boucle bornée et non bornée
Pour la boucle bornée for, il n’est pas necessaire d’ajouter une instruction dans le bloc pour que le variant change de valeur à chaque itération. Cela se fait tout seul, à chaque fois que le programme revient sur l’instruction for.
Remarque: la fonction range(3) va créer une liste itérable constituée des valeurs 0, 1, 2. Ce sont les valeurs prises successivement par le variant i dans for i in range(3)
Voici le programme équivalent, utilisant une boucle NON BORNEE while:
# Boucle non bornéei=0whilei<3:print(i)i=i+1# affiche012
Remarque: Avec une boucle non bornée, il faut:
déclarer la valeur initiale du variant: i = 0
écrire la condition d’execution après le while, i<3
faire varier le variant dans la boucle while, i = i+1
Exemple 2: Ce variant peut être utilisé pour une formule mathématique, à l’intérieur de la boucle:
# boucle bornéeforiinrange(3):x=i*7print(x)# affiche la table de 70714
# boucle non bornéei=0whilei<3:x=i*7print(x)i=i+1# affiche la table de 70714
1. Definition: Une chaine de caractère est une séquence ordonnée de caractères, mis entre guillements (simples ' ou doubles "). C’est le type str en python. Pour en savoir plus sur les chaines, on pourra consulter la page: google dev: chaines
On accède à un élément d’une chaine grace à sa position, appelée indice. Le premier élément a pour indice zero.
>voyelles='eio'>voyelles[0]e>voyelles[1]i>voyelle[2]o>voyelles[-1]o# le dernier element de la liste>voyelles'eio'
Un indice négatif permet d’identifier les éléments à partir de la fin: -1 pour le dernier caractère, -2 pour l’avant dernier, …
Illustration avec la chaine de caractères Hello:
exemple avec les rangs des caractères du mot Hello
2. Modifier une chaine
Contrairement aux listes, il n’est pas possible de modifier un caractère dans une chaine:
3. Une fonction utile aux chaines: len
La fonction len va retourner la longueur de la chaine de caractères.
>chaine='abc'>len(chaine)3
Listes
1. Definition: Une liste est une collection ordonnée d’objets.
Une liste est entourée de crochets[ ]. C’est le type list en python. Pour en savoir plus sur les listes, on pourra consulter la page: google dev: listes
On accède à un élément d’une liste grace à sa position, appelée indice. Le premier élément a pour indice zero.
La liste `voyelles` est une collection contenant les caractères
Un indice négatif donne accès à la liste à partir du dernier élément.
2. Modifier les éléments d’une liste
On ne peut modifier un élément d’une liste que si celui-ci existe. Par exemple, si l’on veut modifier l’élément “e” au rang zero de la liste voyelles par un “a”, il faut faire:
demonstration avec python_puzzle. La boucle realise 4 itérations.
Remarques:
Le bloc d’instruction sera executé n fois. Celui-ci peut contenir une ou plusieurs instructions, du moment qu’elles sont bien positionnées dans le bloc.
En Python, le bloc est identifié par une indentation: un retrait par rapport au bord gauche, comprenant 2 espaces (ou 4).
Pour sortir du bloc, on élimine l’indentation (on revient sur le bord gauche)
La fonction range(n) renvoie la liste des entiers de 0 à n-1. C’est un principe général en informatique, on commence toujours à compter à partir de 0, et il faut donc s’arrêter à n-1 pour effectuer n fois la boucle.
Pour chaque itération, le variant i prend une nouvelle valeur de l’ensemble {0,1,2,... n-1}, et peut être utilisé dans le bloc d’instructions.
On peut choisir n’importe quel nom pour le variant, pas seulement i.
Exemple
forcinrange(3):print(c)# affiche012
Remarque:range(3) va créer une liste itérable constituée des valeurs 0, 1, 2. Ce sont les valeurs prises successivement par le variant c dans for c in range(3)
2. Parcourir les éléments d’une liste L avec range(len(L))
Remarque: Rappelez-vous que len(L) est une fonction qui retourne la longueur de la liste L. Si L contient 3 éléments, alors len(L) vaut 3.
3. Parcourir les éléments d’une liste L avec in L
L=["a","b","c"]forcinL:print(c)# afficheabc
Ramarque: Cette fois-ci, le variant c prend successivement toutes les valeurs de la liste L.
Conclusion: Itérable et variant de boucle bornée
Les instructions for i in range(len(L)) et for c in L ont à peu près le même objectif: celui de parcourir TOUS les éléments de la liste L.
Ce qui est COMMUN: c’est l’utilisation du mot clé IN, qui va créer ce que l’on appelle un itérable, c’est-à-dire une liste de valeurs qui seront proposées l’une après l’autre pour le variant de boucle.
Ce qui est DIFFERENT: Dans le premier cas, on utilise la fonction range, qui créé un itérable entre 0 et la valeur mise en paramètre (valeur -1 pour être exact). Ce sont par exemple les indices de la liste L.
# exemple 1
for i in range(5):
# instruction
La boucle va s’executer 5 fois. Mais à chaque fois, le variant i prend successivement l’une des valeurs dans [0,1,2,3,4]
# exemple 2
L = [0, 10, 20, 30]
for c in L:
# instruction
L’instruction for c in L va, elle, créer un itérable constitué des valeurs de la liste L
Le nombre d’itération sera égal au nombre len(L), soit 4. Au cours des itérations, le variant c va prendre successivement chaque valeur de L, soit [0, 10, 20, 30]
Tracer un graphique y = f(x)
Pour tracer un graphique y=f(x), il faut disposer de 2 listes de mêmes dimensions x et y. Les coordonnées des points sont alors:
(x[0],y[0]) pour le point M0
(x[1],y[1]) pour le point M1
…
On utilise la fonction plt.scatter (nuage de points) ou bien plt.plot (courbe) du module matplotlib.pyplot qui est importé à la premiere ligne du script de la manière suivante: import matplotlib.pyplot as plt
Les 2 listes sont positionnées entre parenthèses, dans l’ordre (liste des X, liste des Y). Ce sont les arguments de la fonction plt.scatter (ou de plt.plot).
1. Definition: Une fonction permet d’encapsuler un bloc d’instructions et de lui donnéer un nom:
def ma_fonction():
# bloc de code ligne 1
# bloc de code ligne 2
La fonction est déclarée après le mot-clé def.
Choisir un nom qui n’appartient pas à Python (aucune autre fonction porte ce nom dans le langage).
Le nom est suivi de parenthèses () et deux points :
Le bloc de code de la fonction est indenté sous la ligne def ma_fonction
Appel de fonction: On peut ensuite exécuter ce bloc en utilsant ce nom. On dit qu’on appelle cette fonction en écrivant son nom, suivi de parenthèses ().
ma_fonction()
Valeur de retour: Une fonction retourne en général une valeur. Après le mot-clé return
Exemple 1 Dans ce script, on definit une fonction qui retourne Hi. Les lignes commençant par le symbole # sont des commentaires, et ne sont pas executées par Python. Elles sont optionnelles.
# definition de la fonctiondefhello():return'Hi'# appel de la fonctionhello()# 'Hi'
Fonction avec paramètre
Une fonction peut avoir un ou plusieurs paramètres qui permettent de transmettre des valeurs au bloc d’instructions. A l’interieur de la fonction, ces paramètres sont traités comme des variables, mais locales: Elles n’existent pas à l’exterieur du bloc.
Il y a alors une affectation: paramètre = argument
Exemple 2 Dans ce script, on definit une fonction qui calcule le carré d’un nombre x.
# definition de la fonctiondefcarre(x):returnx**2# appel de la fonctioncarre(5)# retourne 25
Lors de la déclaration de la fonction, le seul paramètre attendu s’appelera x. Puis lors de l’appel de la fonction carre, l’argument choisi est 5. A l’interieur de la fonction, x vaut 5.
illustration du passage d'argument lors de l'appel de la fonction
La valeur de retour est alors 25: l’intruction return x**2 évalue 5**2, soit 25, avant de retourner la valeur.
Observez comme la fonction Python avec paramètre ressemble à la déclaration d’une fonction en mathématiques:
# en math
f(x) = 10 * x + 20
On peut calculer f(x) pour toute valeur de x en remplaçant x dans $10\times x + 20$ par sa valeur. Par exemple, $f(1) = 10\times 1 + 20 = 30$
# en python
def f(x):
return 10 * x + 20
En python, on appelle cette fonction avec la valeur $x=1$ en écrivant:
f(1)
# retourne 30
Le return correspond au signe = en langage mathématique.
Plusieurs paramètres
Lors de l’appel de la fonction, le ou les arguments passés doivent correspondre aus paramètres attendus. Ils doivent être placés dans l’ordre.
Exemple 3: fonction qui calcule la surface d’un rectangle lorsque l’on divise chacun de ses côtés par un même coefficient c. On aura besoin de la longueur de ses côtés x et y (les 2 premiers paramètres de la fonction). Mais aussi de la valeur c:
# definition de la fonctiondefcalcul_surface(x,y,c):S=(x/c)*(y/c)returnS# appel de la fonction avec x=20 et y=30, c=1.5# 20 sera place en premier argument# 30 sera place en 2e argument# 1.5 sera placé au niveau du 3e argumentcalcul_surface(20,30,1.5)# retourne 266.667
Importer des fonctions
On peut étendre les fonctions du langage en important des fonctions. Celle-ci sont natives, elles font partie du langage python, mais ne sont pas chargées au démarrage.
L’un des modules très utile est, par exemple, le module math. Celui-ci contient de nombreuses fonctions. Pour importer celle qui transforme le angles de degrés en radians, il faut ajouter la ligne suivante au debut du programme:
frommathimportradians
Puis, pour l’utiliser, et transformer 45° en radians, on écrira plus loin dans le programme:
angle=radians(45)print(angle)
Placer un script dans une fonction
Le programme suivant comporte quelques lignes que l’on peut avoir à répéter. Imaginons un robot, chargé de laisser entrer les personnes dont l’age est supérieur ou egal à 18:
age=input('Quel age avez-vous? ')age=int(age)ifage>18:print('Vous pouvez entrer')else:print('Desole, ca ne va pas etre possible')
Il sera plus efficace de placer ces lignes dans une fonction.
Les règles pour écrire une fonction à partir de ce script sont les suivantes:
les entrées et variables sont mises en paramètre: il s’agit de age
Les print sont remplacés par return
Il faut choisir un nom à la fonction, écrit après def
defentrer_en_discotheque(age):ifage>=18:return'Vous pouvez entrer'else:return'Desole, ca ne va pas etre possible'
Lorsque vous executez le programme, … il ne se passe rien. Vous avez seulement chargé la fonction.
Il faut appeler la fonction pour que celle-ci soit executée, par exemple avec:
>entrer_en_discotheque(18)
Voici un exemple d’execution d’une fonction à partir du shell.
1:charger la fonction (executer cellule), 2: appel, 3: sortie
Son execution cesse lorsqu’elle arrive à l’instruction return. Le programme reprend alors son cours.
TP5b boucles et fonctions, traitements automatisés
lecture - ecriture fichier
au cours de ce TP, vous allez apprendre à:
parcourir les caractères ou les éléments d’un fichier
traiter les éléments un par un. Placer les éléments traités dans un fichier
lire/ecrire dans un fichier
Manipuler des fichiers txt en python
Parcourir des séquences
Les séquences, comme le chaines str et les listes list python peuvent être parcourues avec une boucle for. On appelle parcourir le traitement des caractères ou des éléments l’un après l’autre.
Traiter les 2 exercices suivants pour démarrer ce TP.
ex 1: (a) Afficher une image à partir d’une Liste. Compléter le script:
L1=[' ^___^','" o o "','===X===',' " ']forlinL1:print(...
(b) Afficher une image à partir d’une liste de listes de caractères.
Les manipulations qui vont suivre demandent quelques pré-requis. Vous allez tester les instructions suivantes avant de réaliser le TP sur le déchiffrement.
Tester et comprendre chacun des exemples proposés ci-dessous.
Instruction de retour à la ligne \n:
Dans une chaine de caractères, pour faire un retour ligne, on utilise la combinaison de symboles \n.
Exemple:
>>>discours="Je sais ta passion, et suis ravi de voir\nQue tous ses mouvements cèdent à ton devoir ;">>>print(discours)Jesaistapassion,etsuisravidevoirQuetoussesmouvementscèdentàtondevoir;
Afficher le caractère \
\ est un caractère d’echappement. C’est à dire que lorsqu’il est placé dans une chaine de caractères, il n’est pas affiché mais interprété. Pour l’afficher, il faut alors mettre 2 fois le même symbole:
>>>print('\\')\
Décalage de 1 rang pour un caractère “a” -> “b”
On détermine le rang ascii du caractère: rang = ord("a")
On definit un nouveau caractère avec décalage dans l’alphabet: chr
>>>rang=ord("a")>>>car=chr(rang+1)>>>print(car)b
Il s’agit d’un décalage de type monoalphabétique, permettant de chiffrer un texte pour le rendre secret. Ici, la clé de chiffrement est égale à 1. (1 seul rang de décalage).
Ecrire dans un fichier txt
méthode 1: fonctions open et close. On créé un objet qui sert à désigner le fichier. Choisir un nom quelconque, pour l’exemple qui suit ce sera fileout. On utilise la fonction open avec pour paramètres, le nom du fichier (son chemin), suivi du caractère ‘w’ (pour write, ouverture du fichier en écriture).
On peut alors placer du texte dans le fichier à l’aide de la méthode write: fileout.write("...")
Penser alors à fermer le fichier de lecture: fileout.close()
fileout=open('exemple.txt','w')fileout.write("Je sais ta passion, et suis ravi de voir\nQue tous ses mouvements cèdent à ton devoir ;")fileout.close()
On peut alors vérifier le fichier et son contenu en parcourant le dossier avec l’explorateur windows.
méthode 2: système d’instructions with + open
Le programme suivant est équivalent à celui de la méthode 1. Avec le mot clé with, les instructions de d’écriture dans le fichier sont mis dans un bloc, et donc indentées. A la sortie de ce bloc, le fichier est automatiquement fermé, ce qui fait l’economie de l’instruction close, et evite les oublis…
withopen('exemple.txt','w')asfileout:fileout.write("Je sais ta passion, et suis ravi de voir\nQue tous ses mouvements cèdent à ton devoir ;")
Lire le contenu d’un fichier txt
méthode 1: fonctions open et close. On créé un objet qui sert à importer le fichier. Choisir un nom quelconque, pour l’exemple qui suit ce sera file. On utilise la fonction open avec pour paramètres, le nom du fichier (son chemin), suivi du caractère ‘r’ (pour read, ouverture du fichier en lecture).
On peut alors récuperer le contenu textuel du fichier à l’aide de la méthode read. Dans l’exemple ci-dessous, on place le texte du fichier dans la variable texte.
On peut traiter cette variable comme on le souhaite, l’afficher en entier (print(texte)), ou parcourir et traiter les caractères les uns après les autres (for c in texte: ...)
Penser alors à fermer le fichier de lecture: file.close()
Le programme suivant est équivalent à celui de la méthode 1. Avec le mot clé with, les instructions de lecture du fichier sont mis dans un bloc, et donc indentées. A la sortie de ce bloc, le fichier est automatiquement fermé, ce qui fait l’economie de l’instruction close, et evite les oublis…
Télécharger le fichier texte_chiffre.txt (faire un clic droit=> sauvegarder la cible du lien sous…)
le placer dans le même dossier que votre fichier python.
Dans le fichier texte_chiffre.txt, le texte est-il écrit en clair ou est-il chiffré?
Les chiffrements les plus anciens reposaient sur un simple décalage des caractères, comme vu dans les informations préliminaires. Par exemple, avec une clé de décalage égale à 1, le “a” devient un “b”, le “b” -> “c”, etc…
A partir des informations précédentes, écrire un script python qui devra:
Ouvrir le fichier ’texte_chiffre.txt’ en LECTURE
Lire le contenu et le placer dans une variable texte
Ouvrir un nouveau fichier en ECRITURE, que vous appelerez ’texte_dechiffre.txt’
Parcourir les caractères de texte, les uns après les autres: for c in texte:
Dans la boucle for: si le caractère c est différent de \ c’est à dire c != "\\"
déterminer le rang ascii de c
definir un nouveau caractère en essayant la clé de décalage égale à -1
écrire ce nouveau caractère dans le fichier ’texte_dechiffre.txt’
Sinon, écrire \n dans le fichier ’texte_dechiffre.txt'
fermer le-s fichier-s si besoin.
Vérifier alors le contenu de votre fichier ’texte_dechiffre.txt’. Si celui-ci est toujours chiffré, recommencer avec une nouvelle clé (-2, puis -3, …)
Si vous avez terminé:
Utiliser votre script pour créer une fonction que vous appelerez chiffre_dechiffre et qui aura 3 paramètres:
texte0 : le fichier texte d’origine
texte1 : le fichier texte de destination
decalage_ascii : la clé de décalage
Cette fonction devra créer un nouveau fichier texte1 à partir du texte du fichier texte0. Tous les caractères de texte1 seront définis à partir de ceux de texte0 en utilisant une clé de déclage: decalage_ascii
Verifier si Python est installé sur votre ordinateur:
Vous pouvez vérifier cela en ouvrant l’invite de commandes et en tapant:
python --version
Windows: Télécharger le fichier d’installation depuis le site officiel de Python. Lancer l’executable et cocher “Add Python to PATH”. Puis cliquer sur Install now
Linux: Python peut être installé et géré via un gestionnaire de paquets comme apt, yum.
MacOS: utiliser le gestionnaire de paquets brew.
L’installation de Python via ces gestionnaires configure souvent automatiquement le PATH. Cependant, une fois l’installation reussie, la commande python --version peut renvoyer une erreur. Dans ce cas, il faudra ajouter Python à la variable d’environnement PATH: datascientist.fr
Installer un IDE python
Dans ce tutoriel, vous allez installer un editeur Python et suivre un premier tutoriel. Vous aurez besoin d’un ordinateur, PC, Linux ou mac.
Choisir l’un des IDE python ou distribution python proposés ci dessous:
Thonny
Pyzo
Anaconda
Winpython
Vous allez faire vos premiers pas dans l’apprentissage du langage.
Thonny
L’IDE le plus simple et complet à utiliser sera Thonny:
Pour éviter les répétitions inutiles de script, utiliser une fonction carre, qui prendra largeur en paramètre, et qui s’executera lorsque l’on écrira: carre(largeur)
importturtlet=turtle.Turtle('turtle')t.speed(8)t.width(2)defcarre(largeur):t.pendown()t.color('red')t.forward(largeur)t.left(90)t.forward(largeur)t.left(90)t.forward(largeur)t.left(90)t.forward(largeur)t.left(90)t.penup()largeur=int(input('entrer la largeur'))carre(largeur)turtle.done()
Un script Python devra suivre une certaine structure pour la position de l’import des modules, déclaration de variables, des fonctions, et enfin le programme principal:
premier script avec le module turtle
Le programme principal finira par turtle.done(), ce qui execute le tracé.
Modifier la fonction carre: utiliser une boucle bornée
Modifier pour avoir un script qui utilise le moins de lignes possibles pour cette fonction. (Rassembler les instructions t.left + t.forward dans une boucle)
Utiliser pour cela une boucle bornée for.
question 1: recopier le script de votre fonction
Une variante du programme: dessiner un rectangle
Definir et utiliser une fonction rectangle pour tracer un rectangle. On définira une nouvelle variable longueur qui sera utile comme paramètre de la fonction.
La valeur de cette variable sera introduite par une fonction input, comme dans le script précédent.
question 2: recopier le script de votre fonction
Dessiner des rectangles
Reproduire, à l’aide de votre fonction, le dessin ci-dessous. Celui-ci forme 3 rectangles colorés de dimension $80x100$.
rectangles côte à côte
question 3: recopier le script de votre programme (ne pas préciser les import et les definitions de fonctions)
Utiliser un variant de boucle
On utilisera maintenant la valeur de i dans l’instruction for i in range(N):
Pour dessiner la figure suivante, on utilisera une boucle bornée, qui répète plusieurs fois le bloc de code:
calculer la valeur de x
dessiner un carré de largeur x
lever le stylo
avancer jusqu’à la prochaine position.
La valeur du paramètre x, dans la fonction carre(x), dependra du variant i.
Ecrire un programme qui réalise ce dessin, à partir d’une fonction mathématique $x = a.i + b$
question 4: recopier le script de votre programme.
Dessiner des spirales
Avec des carrés emboités
Dans un carré de côté 100, on trace un carré dont les sommets sont situés au tiers des côtés du carré initial, et on répète indéfiniment l’opération.
On utilisera une boucle non bornéewhile avec le variantlargeur. La condition d’execution pourrait être par exemple, largeur>20:
whilelargeur>20:# instructions
A chaque itération:
dessiner un carré avec la fonction carre et le paramètre largeur.
avancer de $1/3 \times largeur$
tourner de 26.565 degrés
reduire la largeur d’un facteur 0.745: largeur = largeur * 0.745
question 5: recopier le script de votre programme principal
Avec des segments
Ecrire une fonction spirale qui devra reproduire une figure sur le modèle de la suivante:
La fonction utilisera un paramètres: la longueur du segment initial
le nombre d’itérations N voulues
Dans la fonction spirale: utiliser une boucle (for ou while) pour executer un certain nombre de traits.
TP3 Projet ascii art: des pixels aux symboles ascii
On va remplacer dans une image la couleur d’un pixel par un caractère ascii dont le remplissage permettra de faire varier la clarté d’un zone de l’image.
Video explicative:
lire la video
Télécharger les documents sources et décompresser l’archive. Trouver dans ce dossier les fichiers Marylin-original.jpg et le module display_image
Ouvrir un fichier python dans le même dossier. Importer les modules suivants:
fromPILimportImagefromdisplay_imageimport*
Votre code devra ensuite:
Ouvrir en LECTURE le fichier image à traiter.
redimensionner cette image de façon à ce qu’elle n’ait que 500 pixels de large/haut:
déterminer une série de caractères allant dans un ordre croissant d’opacité:
" " l’espace correspond à un pixel blanc
“@” peut être choisi comme le caractère le plus noir
choisir des caractères intermédiaires
ascii_char=' .:-=+....@'
Ouvrir en ECRITURE le ficher de destination, celui dans lequel on écrira les symboles ascii:
fileout=open("ascii_art.txt","w")
Comme vu dans la video:
Parcourir les pixels de l’image à l’aide de 2 boucles for
Lire la couleur de chaque pixel: rgb=image.getpixel((x,y))
calculer la valeur en niveau de gris du pixel à partir de sa luminosité: grey = (rgb[0]+rgb[1]+rgb[2])//3
attribuer à chaque pixel un caractère: calculer l’indice correspondant dans la liste ascii_char: index = grey * 9 // 255
puis l’écrire dans une chaine de caractères: line += ascii_char[index] + ' '
mettre '\n' en fin de ligne et passer à la ligne suivante.
Une fois la chaine de caractère terminée:
placer la chaine line dans le fichier ascii_art.txt: fileout.write(line)
fermer le fichier txt: fileout.close()
Voila, vous pouvez maintenant vérifier son contenu en l’ouvrant avec un editeur de texte, type bloc notes. Mais pour visualiser l’image représentée par ces caractères, il faudra ajouter les lignes suivantes à votre programme:
Pygame est un module python qui offre des outils permettant de créer des jeux. C’est un programme libre, et opensource.
Le jeu Pong SOLO
Dans cette première partie, nous allons nous familiariser avec l’environnement de developpement et la programmation de type evenementielle, en temps réel. Dans ce type de programmation, il faudra afficher et mettre à jour l’image en fonction des actions du joueur, et lire régulièrement les états des touches du clavier pour detecter les appuis par le joueur.
Programmons ainsi un grand classique des jeux d’arcade: PONG
Dans la variante proposée ici, le jeu se jouera en SOLO, le but étant de renvoyer la balle vers le bord gauche de l’écran.
Dessiner la fenêtre graphique et placer un objet
Commencer par créer un nouveau projet (nouveau fichier: pong.py).
Le programme suivant va dessiner une raquette (un rectangle blanc vertical) dans une fenêtre graphique de dimension 512 x 512 pixels.
Les programmes python avec le module pygame ont toujours à peu près la même structure:
les premières lignes contiennent les extensions à ajouter au langage python.
Ajouter ensuite pygame.init() pour initialiser les modules importés… et terminer le programme par pygame.quit() pour quitter la fenêtre pygame.
l’instruction fenetre = pygame.display.set_mode((512,512)) va créer une fenêtre graphique.
La boucle while continuer: c’est ici que l’on va mettre les instructions du jeu. Le booléen continuer va permettre de gérer la fin de l’execution du programme lorsque l’on ferme la fenêtre avec
if event.type == QUIT: continuer = False
Il s’agit d’une programmation de type evenementielle: il faut tester à chaque nouvelle itération dans la boucle while quelle est la touche sur laquelle le joueur a appuyé, et modifier le décors en conséquence.
Pour dessiner un rectangle de 16 pixels en largeur sur 128 en hauteur, il faudra utiliser la fonction pygame.draw.rect. Les 3 paramètres de la fonction sont:
le nom donné à la fenêtre pygame: fenetre
un tuple constitué des 3 valeurs en code (rouge,vert,bleu): (255,255,255)
un tuple constitué de 4 valeurs: les coordonnées x,y du coin supérieur gauche du rectangle, sa largeur et sa hauteur: (450,r1_y,largeur,hauteur)
exemple de rectangle de dimension 4px x 24 px
Le repère (x,y) de la fenêtre graphique a pour origine (0,0) le coin supérieur gauche. L’axe croissant des x est dirigé vers la droite, et celui des y vers le bas.
Ainsi, pour positionner un rectangle blanc de dimension 4 x 24 à la position A(115,56), la fonction s’écrirait pygame.draw.rect(fenetre,(255,255,255),(115,56,4,24)).
position du coin superieur gauche du rectangle en (115,56)
Contrôler le deplacement d’un objet
On veut deplacer l’objet à l’aide des touches du clavier UP et DOWN (flèches vers le HAUT/BAS):
contrôle de la raquette du jeu PONG
Il faudra appliquer les modifications suivantes:
Rappelez vous que la coordonnée $y_A$ du rectangle est stockée dans une variable: r1_y. La valeur de cette variable est déclarée au debut du programme. Notez que pour l’instant, la raquette reste fixe, et qu’elle n’est pas contrôlable.
Pour lire les touches du clavier, il faut contrôler les evenements, c’est à dire les interactions (clavier, souris).
Pour vérifier si une touche du clavier a été enfoncée, on place l’instruction event.type == KEYDOWN dans le programme:
Et enfin, pour savoir si cette touche était la flèche de direction vers le haut, c’est event.key == K_UP
ifevent.type==KEYDOWN:ifevent.key==K_UP:# deplacer vers le haut
Comment traduire en python: déplacer vers le haut?
Il faudra modifier la valeur de la variable r1_y… Pour déplacer la raquette de 8 pixels vers le haut, choisir la bonne proposition parmi les 2 suivantes:
r1_y = r1_y + 8
r1_y = r1_y - 8
A cette étape, le script du programme est alors:
importpygamefrompygame.localsimport*fromrandomimportrandintpygame.init()pygame.key.set_repeat(1,20)# gestion appui prolongéfenetre=pygame.display.set_mode((512,512))fenetre.fill([0,0,0])r1_y=232largeur=16hauteur=128continuer=Truewhilecontinuer:foreventinpygame.event.get():ifevent.type==QUIT:continuer=Falseifevent.type==KEYDOWN:ifevent.key==K_UP:# instruction qui modifie r1_yfenetre.fill([0,0,0])pygame.draw.rect(fenetre,(255,255,255),(450,r1_y,largeur,hauteur))pygame.display.update()pygame.time.wait(10)pygame.quit()
Que reste t-il à faire?
Si vous executez votre programme, vous pouvez voir votre raquette disparaitre par le bord supérieur de la fenêtre. Il faudra rajouter une condition pour modifier r1_y si r1_y >0. Sinon ne rien faire.
Et si l’on veut faire descendre cette raquette? Utiliser alors if event.key == K_DOWN: et programmer le deplacement vers le bas. Ici aussi, ajouter une condition sur r1_y pour que la raquette ne disparaisse pas par le bord inférieur…
Enfin, lorsque tout fonctionne, vous allez vous interesser au programme de la balle rebondissante: suite du TP
On peut ajouter le contenu d’une variable dans du texte. Il faut pour cela utiliser un formatage. Les symboles {} devront se trouver à l’emplacement de la variable à disposer dans le texte :
Exemple : (executer la cellule suivante)
n=18texte='je viens d\'avoir {} ans'.format(n)print(texte)
Listes
Avec la liste suivante :
mois = ['janvier','fevrier','mars','avril','mai','juin','juillet','aout']
compléter la liste des mois de l’année (utiliser l’une des méthodes de liste)
Quelle instruction, utilisant un indice numerique va retourner le mois ‘juin’ ?
Quelle instruction permettra de retourner la liste suivante, découpée à partir de celle mois? :
['juillet','aout']
Utiliser une expression formatée utilisant mois pour afficher le texte :
Le mois de juin est celui du début de l’été.
Dictionnaire
Soit un dictionnaire : dico = {1:2,3:4} ayant pour couples:
clé 1 : valeur 2
clé 3 : valeur 4
Pour accéder à la valeur 2, il faut faire :
dico[1]
Et pour accéder à la valeur 2, il faut faire :
dico[3]
Le type des clés et des valeurs peut être différent d’un entier : il peut s’agit d’une chaine de caractère, mais aussi d’une liste, d’un tuple, d’un autre dictionnaire…
Exercice :
Avec le dictionnaire :
dico = {1:2,3:{4:5}}
Trouver l’expression qui aura pour valeur : 5
Même exercice, mais on dispose maintenant du dictionnaire :
dico = {'1':'2','3':{'4':'5'}}`
Trouver l’expression qui aura pour valeur, l’entier 5
On dispose d’un dictionnaire de nom laby contenant les données suivantes :
laby = {1:{2:{3:9,5:6},7:8}}
Ecrire une série d’instructions qui permettent de parcourir les valeurs jusqu’à renvoyer la valeur 9.
Mini projet
Ecrire un programme qui permettra de parcourir la galerie de l’entrée (n°1) jusqu’à la sortie (n°9).
la galerie sera représentée par la structure :
galerie = {1:{2:{3:9,5:6},7:8}}
Le programme demande à l’utilisateur de choisir une nouvelle direction à chaque nouvelle clé visitée.
Le programme affiche les choix possibles (valeurs) pour chacune des clés visitées.
L’utilisateur choisit alors une valeur numérique en rapport avec les valeurs possibles et la saisit dans une boite de dialogue générée par la fonction input.
Une boucle while permet de répéter cette séquence tant que la valeur saisie n’est pas 9.
Le texte affiché par le programme :
vous etes au n°1
vous pouvez aller à : [2, 7]
quel est votre choix (1,..9) ? => 2
vous etes au n°2
vous pouvez aller à : [3, 5]
quel est votre choix (1,..9) ? => 3
vous etes au n°3
vous pouvez aller à : 9
quel est votre choix (1,..9) ? => 9
vous avez gagné `
Xyzzy Blast, premier jeu de rôle sur ordinateur
Extension du projet (term NSI)
Ce mini projet peut être étendu. On pourra utiliser des classes pour la gestion du (des) scenario(scenatii), du (des) joueur(s).
On pourra également proposer une interface qui améliorera le confort de jeu.
Enfin, on pourra utiliser des fichiers textes (voire une base de données) pour une meilleure gestion des contenus, ou pour sauvegarder des éléments du jeu.
Le site pyxelstudio.net permet de créer un jeu de type retro-gaming, en python. Il s’agit de jeux que l’on trouvait sur console 8 bits (16 couleurs, 4 pistes audio utilisant 64 sons différents).
console Gameboy, Nitendo, 1990
Le projet est soutenu activement, on peut consulter les démos et les télécharger depuis la page github.com/kitao/pyxel.
Pour créer notre premier jeu, nous allons utiliser l’editeur en ligne pyxelstudio.net.
Il est recommandé de créer un compte afin de retrouvez tous vos projets dans votre espace personnel. Cliquer alors sur register (en haut à droite) et renseigner vos identifiants.
Le jeu Pong SOLO
Dans cette première partie, nous allons nous familiariser avec l’environnement de developpement et la programmation de type evenementielle, en temps réel. Dans ce type de programmation, il faudra afficher et mettre à jour l’image en fonction des actions du joueur, et lire régulièrement les états des touches du clavier pour detecter les appuis par le joueur.
Programmons ainsi un grand classique des jeux d’arcade: PONG
Dans la variante proposée ici, le jeu se jouera en SOLO, le but étant de renvoyer la balle vers le bord gauche de l’écran.
Dessiner la fenêtre graphique et placer un objet
Commencer par créer un nouveau projet (new project).
Cela devrait ouvrir une nouvelle fenêtre (edition).
Lorsque vous reviendrez au tableau de bord (flèche en haut à gauche), modifiez le nom de votre projet.
Remplacer NO NAME par un nom plus evocateur, par exemple Pong raquette.
Depuis le tableau de bord, pour programmer le jeu, cliquer sur le bouton edition (le petit stylo):
La fenêtre d’edition comprend l’editeur à gauche, où l’on peut rediger le script en python, et la rendu visuel du jeu à droite. Celui-ci s’execute lorsque l’on appuie sur le bouton jaune, play:
Parmi les autres commandes de la fenêtre, repérer celle qui permet de sauvegarder et celle qui permet de revenir au tableau de bord.
Le programme suivant va dessiner une raquette (un rectangle blanc vertical) dans une fenêtre graphique de dimension 124 x 124 pixels.
importpyxelpyxel.init(128,128,title="Pong Solo")defdraw():pyxel.cls(0)# vide la fenetrepyxel.rect(115,56,4,24,7)pyxel.text(50,5,'Pong raquette',7)# Affichage Titre pyxel.run(draw)
Les programmes python pour Pyxel Studio ont toujours à peu près la même structure:
la première ligne contient les extensions à ajouter au langage python. Il faudra ajouter au minimum le module pyxel pour notre programme.
l’instruction pyxel.init(128, 128, title="...") va créer une fenêtre graphique carrée de côtés 128 pixels. Ne pas modifier ces dimensions.
On definit une ou plusieurs fonctions pour dessiner, ou calculer de nouvelles coordonnées pour les objets. Ici, nous choisissons d’appeler cette fonction draw pour:
effacer l’image: pyxel.cls(0)
dessiner le rectangle blanc: pyxel.rect(115, 56, 4, 24, 7)
écrire dans la fenêtre graphique: pyxel.text(50, 5, 'Pong raquette', 7)
La dernière ligne, pyxel.run(draw) va executer en boucle l’appel à la fonction draw, qui est citée en paramètre. Cet appel est réalisé 30 fois par seconde. C’est ce qui donne l’impression de dessin animé lorsque l’on modifie la position d’un objet.
Pour dessiner un rectangle de 4 pixels en largeur sur 24 en hauteur, il faudra utiliser la fonction pixel.rect.
rectangle de dimension 4px x 24 px
Pour positionner le rectangle à un endroit précis de la fenêtre graphique, ce sont les coordonnées (x,y) du coin supérieur gauche (le point A sur le schéma) qu’il faut renseigner.
Le repère (x,y) de la fenêtre graphique a pour origine (0,0) le coin supérieur gauche. L’axe croissant des x est dirigé vers la droite, et celui des y vers le bas.
Ainsi, pour positionner le rectangle de dimension 4 x 24 à la position (115,56), la fonction s’écrit pyxel.rect(115, 56, 4, 24, 7). La dernière valeur, le 7 correspond à la couleur BLANC.
position du coin superieur gauche du rectangle en (115,56)
Contrôler le deplacement d’un objet
On veut deplacer l’objet à l’aide des touches du clavier UP et DOWN (flèches vers le HAUT/BAS):
contrôle de la raquette du jeu PONG
Il faudra appliquer les modifications suivantes:
placer la coordonnée $y_A$ du rectangle dans une variable. Appelons celle-ci r1_y par exemple.
La valeur de cette variable sera déclarée au debut du programme, après la première ligne. A cette étape, le script du programme est alors:
importpyxelr1_y=56pyxel.init(128,128,title="Pong Solo")defdraw():pyxel.cls(0)# vide la fenetrepyxel.rect(115,r1_y,4,24,7)pyxel.text(50,5,'Pong raquette',7)pyxel.run(draw)
Notez que pour l’instant, la raquette reste fixe, et qu’elle n’est pas contrôlable.
Pour lire les touches du clavier, il faut utiliser la fonction pyxel.btn, et préciser en paramètre la touche que l’on veut observer. Par exemple, pour lire l’état de la touche UP, ce sera pyxel.btn(pyxel.KEY_UP)
Cette fonction retourne un booléen (True/False), que l’on va placer dans une instruction conditionnelle:
ifpyxel.btn(pyxel.KEY_UP):# deplacer vers le haut
Comment traduire en python: déplacer vers le haut?
Il faudra modifier la valeur de la variable r1_y… Pour déplacer la raquette de 2 pixels vers le haut, choisir la bonne proposition parmi les 2 suivantes:
r1_y = r1_y + 2
r1_y = r1_y - 2
Ou placer cette instruction?
Pour structurer au mieux notre programme, nous placerons les instructions de lecture du clavier et de modification des coordonnées dans une nouvelle fonction, que l’on appelera r1_move
La première ligne de cette fonction doit préciser que l’on autorise la modification de la variable r1_y, alors que cette variable a été déclarée en dehors de la fonction. Il faut placer pour cela l’instruction global r1_y.
Notez qu’à la dernière ligne, on a ajouté la fonction r1_move comme paramètre de pyxel.run. Il y a maintenant 2 fonctions à executer en continu, 30 fois par seconde pour générer le jeu en temps réel.
Que reste t-il à faire?
Si vous executez votre programme, vous voyez votre raquette disparaitre par le bord supérieur de la fenêtre. Il faudra rajouter une condition pour modifier r1_y si r1_y >0. Sinon ne rien faire.
Et si l’on veut faire descendre cette raquette? Utiliser alors if pyxel.btn(pyxel.KEY_DOWN): et programmer le deplacement vers le bas. Ici aussi, ajouter une condition sur r1_y pour que la raquette ne disparaisse pas par le bord inférieur…
Enfin, lorsque tout fonctionne, vous allez vous interesser au programme de la balle rebondissante. Il s’agit alors d’un nouveau projet: Suite
Cette version du programme n’utilise pas les sequences comme les listes python.
L’interface se passe dans la console python.
Principes retenus pour le jeu
L’ordinateur tire 4 couleurs parmis Jaune, Orange, Cyan, Rouge, Vert. Ces pions colorés sont les variables o1, o2, o3, o4. On y stocke un unique caractère, parmis (‘J’,‘O’,‘C’,‘R’,‘V’)
Le joueur doit proposer sa sequence de 4 couleurs. Sa première reponse est placée dans la variable j1, puis la 2e dans j2, etc… Le joueur proposera par exemple ‘J’, puis ‘O’, puis ‘C’, puis ‘R’ pour Jaune, Orange, Cyan, Rouge.
Si la couleur du pion est trouvée, le score Noir N augmente de 1.
Si l’une des couleurs est trouvée mais n’est pas à la bonne place, c’est le score blanc B qui augmente.
Commençons par les variables globales du jeu
Importer la fonction random.choice. Puis utiliser cette fonction pour réaliser le tirage aléatoire d’un caractère parmis ('J','O','C','R','V'), que l’on placera dans la variable o1.
Faire de même pour les 3 autres pions, o2, o3, o4.
Il s’agit de la combinaison tirée par l’ordinateur.
Vous pouvez créer une chaine de caractères à partir de ces 4 variables, en les ajoutant chacune:
sequence=o1+o2+...# a completer
Vous pouvez l’afficher dans la console en ajoutant la fonction print
Vous aurez aussi besoin:
du nombre d’essais réalisés par le joueur
du nombre de pions noirs calculés par l’ordinateur (4 noirs = gagné)
Ajouter alors les lignes qui affectent la valeur 0 à chacune de ces variables, essais et N
Boucle principale du jeu
Ecrire une boucle while avec pour condition d’execution:
le nombre d’essais est <= 12
N est différent de 4
Si l’une de ces conditions n’est plus réalisée, alors on sort de la boucle car la partie est terminée.
Demander au joueur de rentrer les 4 couleurs de sa proposition pour le tour. Utiliser le modèle ci-dessous et programmer j2, j3 et j4
j1=input("entrer la couleur du pion 1 (JOCRV): ")
A cette étape du projet, votre script devrait ressembler à ceci:
fromrandomimportchoiceo1=choice(('J','O','C','R','V'))o2=.........sequence=o1+o2+...# print(sequence)essais=...N=...whileessais...12andN...4:j1=input("entrer la couleur du pion 1 (JOCRV): ")j2=.........
Il faudra ensuite initialiser les variables N et B à zero, puis écrire une série de tests:
Tester pour chaque couleur donnée par le joueur, si celle-ci est bien en correspondance avec le pion de l’ordinateur, à la même place. Par exemple, j1 est il egal à o1: Augmenter alors N d’une unité.
Si le test est negatif, tester alors si la couleur proposée par le joueur est présent dans la sequence, mais occupe une autre position:
Cette fois, ce sera la variable B (pour Blanc), qui augmente d’une unité.
Rq: Lorsque le joueur propose plusieurs fois la même couleur, le test j1 in sequence peut donner de fausses detections. Ce qui surevalue la valeur de B. Pour resoudre ce problème, il faudra utiliser des listes python pour mettre en correspondance les choix joueur et choix ordinateur. Pour ce premier TP, nous allons ignorer ce problème.
Afficher ensuite B et N dans la console, augmenter le nombre d’essais d’une unité, et recommencer la boucle while
Fin de la partie
A la sortie de la boucle while, le joueur a soit gagné, soit perdu. Afficher un message dans la console.
Améliorations possibles
Le joueur pourrait donner sa sequence de couleurs en une seule fois, à l’aide d’une seule commande input. Il écrirait par exemple “JJOV”.
Pour comparer chaque couleur, avec chaque pion de l’ordinateur, à la même position: il faut alors atteindre l’une des lettres du mot “JJOV”, et la comparer à la lettre du même rang, dans la sequence de l’ordinateur.
Lorsque les pions sont en correspondance, il faudra utiliser une liste de correspondance pour marquer les positions deja evaluées.
Exemple:
ordinateur=['J','O','C','V']# on copie la liste ordinateur dans une nouvelle liste# ordinateur -> correspondancecorrespondance=['J','O','C','V']joueur=['J','J','O','O']
Gestion des pions noirs: Lorsque l’on evalue la correspondance de joueur[0], on trouve que joueur[0] == ordinateur[0]. On modifie alors la liste de correspondance de la manière suivante: ['X','O','C','V'], et on poursuit avec joueur[1] == ordinateur[1]…
Gestion des pions blancs: Après la gestion des pions noirs, on recherche les occurences entre joueur[i] et correspond[j] avec i different de j. A chaque nouvelle occurence, on place ‘X’ dans correspond[j], pour ne pas le compter plusieurs fois.
Cela necessite d’utiliser un index pour parcourir le mot du joueur. Et une boucle bornéefor pour faire evoluer le rang.
Le pierre-feuille-ciseaux, chifoumi, pierre-papier-ciseaux ou encore roche-papier-ciseaux est un jeu dans lequel chaque joueur forme simultanément une parmi plusieurs armes symbolisées par la forme de la main et dont les rapports d’efficacité suivent un cycle : la pierre (aussi appelée « caillou » ou « roche ») battant les ciseaux, qui battent la feuille (ou « papier »), qui elle-même bat la pierre. Si les armes choisies sont les mêmes, il y a égalité. wikipedia
consulter les règles du jeu
Programmer un jeu à 2 joueurs
Pour programmer le choix de l’ordinateur: On utilisera la fonction randint du module random. Tester le script suivant pour comprendre son fonctionnement:
Rappels sur les algorithmes vus en classe de 1ere NSI calculer
multiplier, diviser, recherche du PGCD
rechercher
algorithmes de parcours séquentiel et dichotomique
trier
tri par selection, tri par insertion
algorithmes avancés
algorithme glouton et de recherche des K plus proches voisins
traitement des donnees en table
Open datas, csv, module requests, donnees en table
graphique avec matplotlib
Tracé de graphiques avec curseur, contexte graphique
regression lineaire
regression, modelisation avec scipy.optimize
sql et python
traitement sql et visualisation
TP exoplanets.db
traitement sql et visualisation a partir des donnees d’exoplanetes
recherche de correlations
module seaborn, visualisation, recherche de clusters dans un nuage de points
kmean et exoplanetes
KNN et module Scikit-learn, previsions
Ce chapitre comprend 2 pages de cours et une page exercices:
La mise au point d’un programme: Lien 1 Création et utilisation de modules: Lien 2 La liste des projets se trouve ici
Modularité Qu’est ce qu’un module ? Un module est un fichier python (d’extension .py) contenant des fonctions. En principe, il n’est pas prévu pour être executé. Pour faire référence aux fonctions de ce module, il faut l’importer depuis le script principal (ìmport module.py`).
Ce chapitre comprend 2 pages de cours et une page exercices:
La mise au point d’un programme: Lien 1 Création et utilisation de modules: Lien 2 Exercice: Lien Programmer en Grand L’infographie ci-contre montre une mesure des lignes de code dans certains programmes conséquents. Les mesures sont en millions de ligne de code:
codebase - millions lines of code visualized
Les types natifs de base, ce sont les types numériques int et float, le type booléen bool, les chaines de caractères str, mais aussi le type None.
le type de « rien » : None
None est la valeur unique du type NoneType. Elle représente l’absence de valeur.
type(None)# affiche <class 'NoneType'>
None est utile par exemple lorsque l’on veut terminer une fonction sans valeur de retour, ou lorsqu’une fonction ne contient pas d’instruction return (c’est alors la valeur de retour implicite) :
deff(x):# instructionsreturnNone
le type booléen : bool
bool est le type des valeurs de vérité : True et False. C’est le résultat des comparaisons (==, <, >=, …) et des expressions logiques.
type(True)# affiche <class 'bool'>
À noter : en Python, bool est un sous-type de int : True vaut 1 et False vaut 0. C’est pourquoi True + True donne 2.
Transformer le type des données
Pour consulter le type d’une donnée : fonction type:
a=3# Créé un objet de type int et lui associe le nom 'a'type(a)# affiche int
Pour transformer vers un autre type de base, on utilise les fonctions int, float, str:
transformer x en …
fonction
integer
int(x)
float
float(x)
string
str(x)
Exemple: tranformer en float:
float(3)# affiche 3.0float('3.8')# affiche 3.8
transformer en int
convertit par exemple un flottant en entier en tronquant la partie décimale du nombre (attention, ce n’est pas un arrondi) :
int(3.5)# affiche 3int(-3.5)# affiche -3 (et non -4 : la troncature se fait vers 0)
ou une chaine de caractères en un entier :
int("3")# affiche 3int("3.5")# ValueError : int() ne convertit que des chaines représentant un entier
Opérations sur les types numériques
Les opérateurs sur les nombres ont été vus dans le cours Python les bases.
Certaines fonctions natives vont enrichir les possibilités de calcul:
Exemple:arrondir : fonction round(nombre,decimales)
`round(3.1415926,2)` donne `3.14`
La bibliothèque math contient de nombreuses fonctions utiles au calcul scientifique:
importmathmath.sqrt(9)# affiche 3.0PI=math.piPI# affiche 3.141592653589793math.sin(PI/2)# affiche 1.0# le sinus de l'angle en radiansmath.fabs(-101)# affiche 101.0# Renvoie la valeur absolue de (-101), toujours sous forme de floatmath.isnan(PI)# affiche Falsemath.isnan(float('nan'))# affiche True# Renvoie True si x est NaN (Not a Number)
Remarque: les nombres flottants ont une précision limitée. Par exemple 0.1 + 0.2 n’affiche pas exactement 0.3 mais 0.30000000000000004, à cause de la façon dont les flottants sont représentés en mémoire (norme IEEE 754). Il faut garder ceci en tête avant de comparer deux flottants avec ==.
Opérations sur les booléens - rappels
operateur
symbole
exemple d’expression
resultat
intersection
and
True and False
False
reunion
or
True or False
True
negation
not
not False
True
est égal à
==
True == False
False
est différent de
!=
True != False
True
Opérations avec les chaines de caractères
Les opérateurs + et * sont autorisés dans les expressions avec les chaines de caractère.
Le + réalise une concaténation de 2 chaines. Le * répète et concatène la chaine :
On peut aussi utiliser des index négatifs (qui comptent depuis la fin de la chaine) et un pas (step) dans le slice :
chaine[-1]# affiche 'd' (dernier caractère)chaine[::-1]# affiche 'dlroW olleH' (la chaine inversée)chaine[0:11:2]# affiche 'HloWrd' (un caractère sur deux)
Mais, contrairement aux Listes, on ne pourra pas modifier un caractère par son index:
chaine[0]='P'# TypeError: 'str' object does not support item assignment
En fait, comme int et float, le type str est immuable (immutable) : une fois créée, une chaine ne peut plus être modifiée en place. Toute méthode qui semble « transformer » une chaine (upper(), replace(), …) renvoie en réalité une nouvelle chaine.
Une chaine de caractères est itérable: On peut la parcourir avec une boucle bornée. Par exemple, le script suivant élimine tous les espaces dans la chaine:
s="Il fait beau."res=""forcaracins:ifcarac!=' ':res=res+caracprint(res)# affiche Ilfaitbeau.
méthodes de chaines
Les chaines sont des objets qui possèdent leurs méthodes. il est difficile de se souvenir de toutes les méthodes travaillant sur les chaînes de caractères. Aussi il est toujours utile de recourir à la documentation embarquée
help(str)
Ce qui donne:
Help on class str in module builtins:
class str(object)
| str(object='') -> str
| str(bytes_or_buffer[, encoding[, errors]]) -> str
|
| Methods defined here:
| ...
| format(...)
| S.format(*args, **kwargs) -> str
|
| Return a formatted version of S, using substitutions from args and kwargs.
| The substitutions are identified by braces ('{' and '}').
| ...
| join(self, iterable, /)
| Concatenate any number of strings.
|
| The string whose method is called is inserted in between each given string.
| The result is returned as a new string.
|
| Example: '.'.join(['ab', 'pq', 'rs']) -> 'ab.pq.rs'
| ...
construire une chaine avec une f-string
pour construire une chaine à partir de valeurs de variables, la syntaxe moderne et recommandée est la f-string, plus lisible que format ou la concaténation avec + :
nom,age='Ada',36chaine=f"{nom} a {age} ans"print(chaine)# affiche 'Ada a 36 ans'
Découpage - assemblage: split et join
Les méthodes split et join permettent de découper une chaîne selon un séparateur pour obtenir une liste, et à l’inverse de reconstruire une chaîne à partir d’une liste.
Remarque: Si le séparateur est un terminateur, comme par exemple ;, ou\n, il conviendra d’utiliser d’abord la méthode strip. Voir Compléments en bas de page.
Remplacement: replace
replace est très pratique pour remplacer une sous-chaîne par une autre, avec une limite éventuelle sur le nombre de remplacements :
"abcdefabcdefabcdef".replace("abc","zoo")# affiche zoodefzoodefzoodef"abcdefabcdefabcdef".replace("abc","zoo",1)# affiche zoodefabcdefabcdef (un seul remplacement grâce au 3e argument)
modifier la casse d’une chaine
utiliser les méthodes title() (titre), upper() (mise en majuscule), lower() (minuscule).
nom='charles babbage'nom.title()# affiche Charles Babbagenom.upper()# affiche CHARLES BABBAGE
Les méthodes lstrip() (à gauche), rstrip() (droite), et strip() (à droite et à gauche) suppriment les espaces en trop dans les chaines.
à tester vous-même :
nom=' charles babbage 'nom.strip()
Compléments sur les variables et types
Valeur et référence
Les variables en Python sont des références nommées.
Une variable est donc une étiquette associée à une valeur. Ce nom est à peu près quelconque, mais pour l’ordinateur il s’agit d’une référence désignant une adresse mémoire, c’est-à-dire un emplacement précis dans la mémoire vive.
À cet emplacement est stockée une valeur typée bien déterminée.
image issue du cours sur http://www.normalesup.org/
Cette valeur peut être en fait à peu près n’importe quel « objet » susceptible d’être placé dans la mémoire d’un ordinateur, par exemple : un nombre entier, un nombre réel, un nombre complexe, un vecteur, une chaîne de caractères, un tableau, une fonction, etc.
Le programme suivant permet de consulter l’adresse mémoire d’une variable:
a=3# Créer un objet de type int et lui associe le nom 'a'type(a)#=> int# Cet objet se trouve dans la mémoire de l'ordinateur# à un endroit que l'on peut obtenir avec `id`:id(a)#=> La position de l'objet nommé a dans la mémoire de l'ordinateur.# Affiche94875962855936
Pour aller plus loin : deux noms peuvent référencer le même objet en mémoire. L’opérateur == compare les valeurs, alors que l’opérateur is compare les références (l’identité, donc le résultat de id) :
a=[1,2,3]b=[1,2,3]a==b# True : mêmes valeursaisb# False : deux objets distincts en mémoirec=acisa# True : c et a référencent le même objet
Typage dynamique
Python est un langage à typage dynamique, ce qui signifie qu’il n’est pas necessaire de déclarer le type de donnée que représentera une variable (c’est la différence avec le typage statique). C’est l’interpréteur qui examine la donnée tout au long de la vie du programme et choisit le type.
Affectation simple et multiple
Affectation simple :
Les termes « affecter une valeur » ou « assigner une valeur » à une variable sont équivalents. Ils désignent l’opération par laquelle on établit un lien entre le nom de la variable et sa valeur (son contenu).
Exemple :a = 2
Lorsque l’ordinateur execute cette instruction, il va :
créer et mémoriser un nom de variable ;
lui attribuer un type bien déterminé (ce point sera explicité à la page suivante);
créer et mémoriser une valeur particulière;
établir un lien (par un système interne de pointeurs) entre le nom de la variable et l’emplacement mémoire de la valeur correspondante.
Le nom d’une variable est une référence, mémorisée dans une zone particulière de la mémoire que l’on appelle espace de noms, alors que la valeur correspondante est située ailleurs.
Affectation multiple :
Il est possible de réaliser une affectation pour plusieurs variables d’un seul coup :
a,b,c=3,True,'hello'b# affiche True
Compléments sur les strings
strip ou split
Si le séparateur est un terminateur, comme par exemple ;, ou\n, la liste résultat contient alors une dernière chaîne vide. En pratique, on utilisera la méthode strip, que nous allons voir ci-dessous, avant la méthode split pour éviter ce problème.
"abc;def;ghi;jkl;".split(';')# retourne ['abc', 'def', 'ghi', 'jkl', '']# le dernier element de la liste est ''
alors que:
"abc;def;ghi;jkl;".strip(';')# retourne abc;def;ghi;jkl# on a supprime le dernier ';'# on peut alors utiliser la methode split:"abc;def;ghi;jkl;".strip(';').split(';')# retourne ['abc', 'def', 'ghi', 'jkl']
PARSER une chaine de caractères
“Parser” signifie analyser et convertir un script en un format interne que l’environnement d’exécution peut interpréter. Il s’agit d’une analyse syntaxique.
Soit la chaine de caractères suivante, issue d’une requête HTTP:
'GET /search ville=nice UTC=12'
On souhaite stocker dans 4 variables différentes les informations séparées chacune par des espaces ’ ‘.
On ne connait pas à priori les positions des séparateurs dans la chaine (les espaces ’ ‘). On peut faire une recherche en parcourant la chaine du premier au dernier caractère avec l’instruction while i < len(c): caract = c[i] ...
i=0caract=c[i]# recherche des espaces dans la chaine cwhilei<len(c):caract=c[i]ifcaract==' ':print(i)i=i+1# affiche les index tels que c[i] == ' '# 3# 11# 22
Les séparateurs se trouvent aux indices 3, 11, et 22. On sait alors que les 4 informations de la chaines sont:
C1=c[:3]C2=c[4:11]C3=c[12:22]C4=c[23:]
méthode split
La méthode la plus adaptée pour réaliser le parsing d’une chaine, c’est:
c.split(' ')# retourne les elements dans une liste# ['GET', '/search', 'ville=nice', 'UTC=12']
Cette page aborde les notions avancées sur les types construits (listes, tuples, dictionnaires). Il peut être nécessaire de consulter les notions de base sur les : boucles et listes.
Les structures de données définissent la manière avec laquelle sont stockées les données dans un langage.
Les types construits, comme les listes et les dictionnaires sont construits à partir des types de bases que l’on a déjà vus. Ce sont d’autres moyens d’organiser et d’agencer les types de base dans d’autres structures.
Les types construits peuvent stocker d’autres types construits.
On distingue les types séquentiels (liste, tuple et string) des mappages (dictionnaires).
Une séquence est une structure de données qui stocke une collection d’éléments dans un ordre déterminé. On accède aux éléments par leur indice (leur rang dans la séquence).
Pour les mappages, il s’agit d’une collection de type clé:valeur. On accède à une valeur par sa clé.
Listes
Definition: Une liste est une collection ordonnée d’objets. Au niveau de la mémoire de l’ordinateur, une liste porte un nom, et fait référence à des espaces mémoire pour chaque élément de liste. Ces éléments (espaces mémoires) font eux-mêmes référence aux emplacements mémoire qui stockent les valeurs ou objets.
En python: Une liste est entourée de crochets[ ]
Les éléments contenus peuvent être de tout type.
On accède à un élément d’une liste grâce à sa position, appelée indice. Le premier élément a pour indice zero.
La liste `voyelles` est une collection contenant les caractères
Un indice négatif donne accès à la liste à partir du dernier élément.
Pour construire une liste par compréhension, on place une boucle bornée à l’INTERIEUR des crochets. Cela crée un élément dans la liste pour chaque valeur de l’itérable.
On peut combiner les expressions entre les crochets, en ajoutant par exemple une condition. Ainsi, si l’on veut uniquement le carré des nombres pairs (if i % 2 == 0):
# carre des nombres pairssquares=[i**2foriinrange(101)ifi%2==0]
Pour construire un tableau à deux dimensions (une liste de listes), on peut imbriquer deux compréhensions de liste:
une découpe est une partie de liste, spécifiée à partir des indices :
etats=['CH','GB','NL','PL','RO','SK']etats[2:4]# affiche ['NL', 'PL']etats[:2]# sans specifier le premier indice# affiche ['CH', 'GB'] # commence au débutetats[3:]# sans specifier l'indice de fin# affiche ['PL', 'RO', 'SK'] # jusqu'à la fin
Copie d’une liste
Une copie d’une liste permet d’utiliser le contenu de la liste copiée sans affecter la liste d’origine (voir TP sur les variables). C’est une copie par valeurs.
Attention: L’instruction $L1 = L2$ est à eviter lorsque l’on veut copier une liste.
A la place, on peut :
la découper sans mentionner les 2 indices:
etats=['CH','GB','NL','PL']mes_etats=etats[:]# liste copiée par valeur dans mes_etats
utiliser la fonction list:
etats=['CH','GB','NL','PL']mes_etats=list(etats)# liste copiée par valeur dans mes_etats
utiliser la fonction copy:
etats=['CH','GB','NL','PL']mes_etats=etats.copy()
On peut alors vérifier qu’il s’agit maintenant d’une copie par valeurs :
Sans cette astuce, la copie se ferait par référence (rappelez-vous: Liste = mutable)
Trier une liste
Il y a 2 fonctions de tri :
La fonction sorted renvoie une copie de la liste triée dans l’ordre croissant (numérique pour des nombres, alphabétique pour des chaînes) sans modifier la liste d’origine.
L=[9,5,1,3,4]sorted(L)# affiche [1, 3, 4, 5, 9]
Puis:
L# affiche toujours [9, 5, 1, 3, 4]
La méthode sort permet de trier la liste en place.
L=[9,5,1,3,4]L.sort()# L est transformee en# [1, 3, 4, 5, 9]
Choix d’un élément aléatoire dans une liste.
Il faut importer la fonction choice de la librairie random:
On accède à l’un des éléments à l’aide de son indice, comme pour les listes.
Par contre, le tuple est non mutable : on ne peut pas en modifier l’un de ses éléments. Il faut refaire, au besoin, une affectation complète de tout le tuple.
elementaire=('CP','CE1','CE2')elementaire[1]# affiche 'CE1'elementaire[2]='CM2'# TypeError: 'tuple' object does not support item assignmentelementaire=('CP','CE1','CM2')elementaire# affiche ('CP', 'CE1', 'CM2')
Non mutable mais avec des éléments mutables:
t=(0,[1,2])t[1].append(3)print(t)# Affiche (0, [1, 2, 3]) ← le tuple n'a pas changé, mais son contenu change
L’immuabilité du tuple garantit que ses références ne changent pas, pas que les objets
référencés sont eux-mêmes figés.
Mappages : les dictionnaires
Un mappage est une structure de données qui relie 2 informations ou plus, appelées paires clé : valeur. Aussi appelée table de hashage. En python, cette structure est le dictionnaire.
Un dictionnaire est entouré d’accolades{ }. Les paires sont séparées par une virgule.
Création d’un dictionnaire
dic={}# creer un dictionnaire videdic=dict()# Variantedic={"nom":"Alice","âge":30}# Création d'un dictionnaire déjà peuplé
Par exemple, pour créer un dictionnaire non vide, on peut faire :
keyindic# Renvoie True ou False, selon que key est ou non une clevalindic.values()# Renvoie True ou False, selon que val est ou non une valeur
Copier un dictionnaire
On peut utiliser la fonction dict pour faire une copie par valeur d’un dictionnaire :
mes_capitales=dict(capitales)
Sans cette astuce, la copie se ferait par référence (Dictionnaire = mutable)
Vider un dictionnaire
On peut aussi aussi utiliser la méthode clear()
Objets mutables et non mutables
En Python, il existe deux types d’objets: les mutables (listes, dictionnaires, sets, objets customisés) et les non mutables (string, int, float, bool, tuple, None).
Les mutables sont ceux qu’on peut modifier après leur création. Les non mutables sont ceux qu’on ne peut pas modifier après création.
Lorsque 2 références pointent sur le même objet, ce qui est possible avec les mutables, il faut s’attendre à ce que la modification de l’un entraine celle de l’autre (effet de bord).
C’est le mot-clé IS qui va permettre de tester si 2 noms pointent vers la même réference en mémoire:
Un effet de bord est une modification d’une variable qui affecte l’état du programme en dehors de la fonction où elle a lieu. Cela peut arriver avec des variables globales, déclarées en dehors de toute fonction.
Pour une variable x non mutable, déclarée dans le corps du programme, celle-ci peut être lue dans une fonction où elle n’a pas été definie. Par contre, pour la modifier dans cette fonction, il faudra la déclarer avec global x dans cette fonction.
Une grande partie des données que l’on manipule en informatique se présentent sous forme de tables : un ensemble d’enregistrements (une ligne par individu, par mesure, par pays…), chacun décrit par les mêmes attributs (les colonnes). C’est le cas d’une feuille de tableur, d’une table de base de données, ou d’un fichier .csv.
Modéliser une table avec des listes
La structure la plus simple pour représenter une table en Python est une liste de listes : chaque ligne de la table est elle-même une liste.
Par convention, on place souvent en première ligne les étiquettes de colonnes (le nom de chaque attribut), puis une ligne par individu :
table=[["Pays","Nb élèves secondaire","Jours de vacances/an","Durée secondaire (ans)"],["France",5660000,112,7],["Allemagne",6900000,65,9],["Espagne",3500000,105,6],["Grèce",700000,119,6],]
Accéder à une valeur
Une table étant une liste de listes, on accède à une valeur précise avec un double indiçage : table[i][j] désigne la valeur de la ligne i, colonne j.
Parcourir les lignes de données (sans l’en-tête) se fait avec une boucle bornée classique :
forligneintable[1:]:print(ligne)
Pour parcourir les lignes et colonnes, on imbrique une seconde boucle, en s’appuyant sur range(len(table[0])) :
forligneintable[1:]:# pour chaque ligne de datasforjinrange(len(ligne)):# j est le numero de colonneprint(table[0][j],":",ligne[j])print("---")
… Affiche …
Pays : France
Nb élèves secondaire : 5660000
Jours de vacances/an : 112
Durée secondaire (ans) : 7
---
Pays : Allemagne
Nb élèves secondaire : 6900000
Jours de vacances/an : 65
Durée secondaire (ans) : 9
---
Pays : Espagne
Nb élèves secondaire : 3500000
Jours de vacances/an : 105
Durée secondaire (ans) : 6
---
Pays : Grèce
Nb élèves secondaire : 700000
Jours de vacances/an : 119
Durée secondaire (ans) : 6
---
Traitement des données en ligne
Pour les exemples qui suivent, le traitement des données d’une table porte sur ses valeurs numériques. Par exemple, avec la somme des données de chaque ligne et leur affichage:
Le parcours de la table entière nécéssite d’utiliser deux boucles imbriquées, afin de parcourir toutes les lignes (indice i), et toutes les colonnes de chaque ligne (indice j).
datas=[[5660000,112,7],[6900000,65,9],[3500000,105,6],[700000,119,6]]foriinrange(len(datas)):# on initialise s à chaque nouvelle lignes=0forjinrange(len(datas[0])):s=s+datas[i][j]# on affiche s a la fin de chaque ligneprint(s)
Traitement de données en colonne
On souhaite faire la somme des valeurs dans la colonne c. On propose cette fois un parcours de la table datas par élément, avec for ligne in datas:
Le cours sur les types construits a montré que copier une liste par simple affectation (copie = original) crée un alias : les deux noms désignent le même objet.
Pour une liste « plate », on évite ce piège avec original[:] ou list(original). Mais pour une liste de listes, il faut être plus prudent :
donnees=table[1:]# copie de la liste externe# donnees vaut [['France', 5660000, 112, 7],... ['Grèce', 700000, 119, 6]]donnees[1][1]=0print(table[1][1])# affiche 0 !! table a été modifiée alors qu'on n'a modifié que "donnees"print(table)# [['Pays', 'Nb élèves secondaire',...], ['France', 0, 112, 7],... ['Grèce', 700000, 119, 6]]
table[1:] crée bien une nouvelle liste externe, mais ses éléments — les lignes — restent les mêmes objets que dans table. C’est une copie dite de surface (shallow copy) : seul le premier niveau est dupliqué.
Pour obtenir une copie totalement indépendante, y compris des lignes, il faut une copie profonde (deep copy), fournie par le module copy :
fromcopyimportdeepcopydonnees=deepcopy(table[1:])donnees[0][1]=0table[1][1]# affiche 5660000 # table n'a pas été modifiée cette fois
Rechercher un extremum dans une colonne
Rechercher, par exemple, le pays ayant le plus grand nombre d’élèves (colonne d’indice 1) suit le schéma classique de recherche de maximum : on mémorise le meilleur candidat rencontré jusqu’ici, et on le met à jour à chaque ligne qui fait mieux.
meilleure_ligne=table[1]# meilleure_ligne vaut ["France", 5660000, 112, 7]forligneintable[2:]:# a la premiere iteration# ligne[1] vaut 6900000ifligne[1]>meilleure_ligne[1]:meilleure_ligne=ligneprint(meilleure_ligne[0],meilleure_ligne[1])# affiche Allemagne 6900000
Trier une table selon une colonne
Le cours sur les types construits a présenté sorted et sort pour trier une liste dans son ordre naturel. Ces deux outils acceptent en réalité un paramètre optionnel, key, qui indique selon quel critère comparer les éléments — utile ici puisqu’on ne veut pas trier des lignes entières « au hasard », mais selon une colonne précise.
key attend une fonction qui, appliquée à un élément, renvoie la valeur à utiliser pour la comparaison. Pour une fonction aussi courte, on utilise en général une fonction lambda (fonction anonyme, écrite en une ligne) plutôt qu’une fonction def complète :
lambdaligne:ligne[1]# équivaut à une fonction sans nom qui, à une ligne, associe ligne[1]
On peut alors trier la table selon le nombre d’élèves, du plus grand au plus petit :
tri_par_effectif=sorted(table[1:],key=lambdaligne:ligne[1],reverse=True)forligneintri_par_effectif:print(ligne[0],ligne[1])# affiche# Allemagne 6900000# France 5660000# Espagne 3500000# Grèce 700000
Documentation (extrait) :
sorted(iterable, key=None, reverse=False)
- key : fonction appliquée à chaque élément avant comparaison
- reverse=True : tri décroissant plutôt que croissant
Tables et dictionnaires
Se repérer dans un dictionnaire
Les tables peuvent être représentées par des dictionnaires imbriqués.
On doit alors accéder à un élément avec un accès profond:
Accéder à une valeur par sa position (ligne[1]) est efficace mais peu lisible : rien n’indique, à la lecture du code, que l’indice 1 correspond au nombre d’élèves. Une alternative consiste à représenter chaque ligne par un dictionnaire, où les clés sont les étiquettes de colonnes.
On peut généraliser cette construction à toutes les lignes de la table, à l’aide d’une boucle, pour obtenir un dictionnaire de dictionnaires — une structure très courante pour représenter des données structurées :
Un fichier CSV (Comma-Separated Values) stocke une table sous forme de texte : chaque ligne du fichier est une ligne de la table, et les valeurs sont séparées par un caractère précis (une virgule , le plus souvent, mais un point-virgule ; est fréquent dans les fichiers produits en France, la virgule y étant déjà utilisée comme séparateur décimal).
Le module csv de la bibliothèque standard permet de lire un tel fichier sans avoir à découper les lignes soi-même avec split :
open('datas/classe.csv', newline='') ouvre le fichier. L’argument newline='' est recommandé par la documentation de csv pour éviter des problèmes de fin de ligne selon le système d’exploitation.
csv.reader(csvfile, delimiter=';') construit un objet itérable : chaque itération donne la ligne suivante du fichier, déjà découpée en liste de chaînes de caractères, selon le séparateur indiqué (ici ;).
La boucle for row in spamreader: parcourt ces lignes une par une, et le script les accumule dans la liste classe avec append — la même technique de construction de liste par accumulation que celle vue avec while/for dans le TP sur les listes.
À la fin, classe est une liste de listes, exactement comme la table table du début de ce cours — on peut donc lui appliquer tout ce qui vient d’être vu : parcours, copie, recherche d’extremum, tri par clé, conversion en dictionnaires.
Point de vigilance : le module csv lit toujours les valeurs comme des chaînes de caractères, y compris les nombres. Une valeur "5660000" lue dans un fichier CSV doit être convertie explicitement avec int(...) ou float(...) avant tout calcul (voir le cours sur les conversions de types).
Pour aller plus loin : le module csv propose aussi csv.DictReader, qui utilise automatiquement la première ligne du fichier comme clés et renvoie directement chaque ligne sous forme de dictionnaire — ce qui réalise en une seule instruction ce que la section précédente a construit à la main :
withopen('datas/classe.csv',newline='')ascsvfile:lecteur=csv.DictReader(csvfile,delimiter=';')forligneinlecteur:print(ligne)# chaque "ligne" est un dictionnaire, par exemple :# {'Pays': 'France', 'Nb élèves secondaire': '5660000', ...}
Complexité d’accès : dictionnaires imbriqués vs listes de listes
1. Le paragraphe de cours
Un dictionnaire Python est implémenté à l’aide d’une table de hachage : chaque clé est transformée par une fonction de hachage en un indice qui pointe directement vers l’emplacement mémoire où se trouve la valeur associée. Ainsi, accéder à dico[cle] ne nécessite pas de parcourir le dictionnaire élément par élément : on calcule l’emplacement directement, ce qui donne une complexité en moyenne constante, $O(1)$, quel que soit le nombre $n$ de couples clé/valeur stockés. Cette propriété se conserve pour les dictionnaires imbriqués : accéder à dico[cle1][cle2] revient à effectuer deux accès en $O(1)$ successifs (un par niveau d’imbrication), donc une complexité globale en $O(1)$ elle aussi, indépendante de la taille du dictionnaire à chaque niveau.
Il en va tout autrement pour une liste de listes. Une liste ne connaît que des positions numériques (des indices 0, 1, 2, ...) : elle ne peut pas retrouver un élément à partir d’une « clé » sans le comparer un par un aux éléments qu’elle contient. Rechercher une valeur associée à un identifiant dans une liste de listes impose donc un parcours linéaire, de complexité $O(n)$ dans le pire des cas (et $O(n \times m)$ si l’on doit chercher dans des sous-listes de taille $m$), $n$ étant le nombre d’éléments parcourus avant de trouver (ou non) celui qui est cherché.
La différence essentielle est donc la suivante : le temps d’accès à une donnée dans un dictionnaire ne dépend (en moyenne) pas du nombre d’éléments qu’il contient, alors que dans une liste, ce temps croît avec le nombre d’éléments à parcourir. C’est ce qui justifie l’usage des dictionnaires — y compris imbriqués — dès qu’une structure de données doit permettre des recherches fréquentes par identifiant plutôt que par position.
2. Schéma
a. Dictionnaire — accès direct par hachage
flowchart LR
K["Clé cherchée<br/>'Chloé'"] --> H["Fonction de hachage<br/>hash('Chloé')"]
H --> I["Indice calculé<br/>ex : 5"]
I --> B["Case n°5 de la table<br/>→ valeur associée"]
style K fill:#e8f4ff,stroke:#3b82f6
style H fill:#fff7e6,stroke:#f59e0b
style I fill:#fff7e6,stroke:#f59e0b
style B fill:#e7f9ed,stroke:#22c55e
Un seul calcul (le hachage de la clé) suffit à localiser la donnée : le nombre d’étapes ne dépend pas du nombre d’éléments stockés.
Ici, il faut comparer la clé cherchée à chaque élément, un par un, jusqu’à la trouver (ou parcourir toute la liste si elle est absente) : le nombre d’étapes croît avec le nombre d’éléments stockés.
3. Exemple chiffré : mesure du temps d’exécution
Le code ci-dessous compare, pour des tailles croissantes de données, le temps nécessaire pour rechercher un élément :
dans un dictionnaire (recherche par clé) ;
dans une liste de listes de la forme [[identifiant, valeur], [identifiant, valeur], ...] (recherche par parcours).
importtimedefconstruire_dictionnaire(n):return{f'id_{i}':iforiinrange(n)}defconstruire_liste_de_listes(n):return[[f'id_{i}',i]foriinrange(n)]defrecherche_dictionnaire(dico,cle):returndico[cle]defrecherche_liste(liste,cle):foridentifiant,valeurinliste:ifidentifiant==cle:returnvaleurreturnNonetailles=[1000,10000,100000,1000000]print(f"{'taille':>10} | {'temps dict (s)':>15} | {'temps liste (s)':>16}")fornintailles:dico=construire_dictionnaire(n)liste=construire_liste_de_listes(n)cle_cherchee=f'id_{n-1}'# dernier élément : pire cas pour la listedebut=time.perf_counter()recherche_dictionnaire(dico,cle_cherchee)temps_dict=time.perf_counter()-debutdebut=time.perf_counter()recherche_liste(liste,cle_cherchee)temps_liste=time.perf_counter()-debutprint(f"{n:>10} | {temps_dict:>15.8f} | {temps_liste:>16.8f}")
Résultat attendu (ordre de grandeur, les valeurs exactes dépendent de la machine) :
taille | temps dict (s) | temps liste (s)
1000 | 0.00000030 | 0.00003500
10000 | 0.00000030 | 0.00035000
100000 | 0.00000030 | 0.00350000
1000000 | 0.00000030 | 0.03500000
Interprétation : le temps de recherche dans le dictionnaire reste (à peu près) constant quelle que soit la taille n, conformément à la complexité $O(1)$. Le temps de recherche dans la liste de listes, lui, est multiplié par 10 à chaque fois que n est multiplié par 10 : il croît linéairement avec n, conformément à la complexité $O(n)$.
Pandas va permettre de lire et de modifier des tableaux (DataFrames). Chaque colonne de ton DataFrame sera appelée « descripteur ». La manipulation d’un dataframe peut ressembler à celle d’une base de données (voir SQL).
Exemple: La table suivante est issu de l’import d’une base de données d’exoplanètes:
Cette table fera l’objet d’une étude spécifique: ici
Présenter les résultats: CSV => Dataframe
Importer les données depuis un fichier csv
Les courbes de transit vont permettre de mesurer les valeurs de profondeur de transit $\delta$ et de durée de transit $\tau$.
Ces valeurs seront reportées dans un fichier csv avec les autres informations sur les planètes et leur étoile. Utiliser un tableur. Attention à bien utiliser des points comme séparateur décimal.
tableau rempli à l'aide d'un tableur
Exporter (ou enregistrer) en format csv.
On peut vérifier en ouvrant le fichier csv que les données sont mises dans un format particulier (séparation à l’aide d’un point virgule…)
fichier csv
L’import depuis pandas se fait alors de la manière suivante: (rien de plus simple)
df=pd.read_csv('exoplanetes.csv',sep=';')df
Ajouter les colonnes utiles aux calculs
un dataframe se comporte comme un dictionnaire dont les clefs sont les noms des colonnes et les valeurs sont des séries:
G=6.67e-11R_Jup=71e6M_Jup=6.9911e7df['tau']=(df['fin_transit']-df['debut_transit'])*24*3600df['delta']=1-df['lum_min']df['M_star']=7.158780e+29# pour TOI-270df['R_star']=257512600.0# pour TOI-270df['R_p']=np.sqrt(df['delta'])*df['R_star']df['radius']=df['R_p']/R_Jup# pour exprimer en R_Jup# vitesse planete : V_p = 2*R_star/taudf['V_p']=2*df['R_star']/df['tau']# rayon orbital : r = G*M_star/V_p**2df['r_orb']=G*df['M_star']/df['V_p']**2# periode revolution: T = 2*np.pi*r/V_pdf['T']=2*np.pi*df['r_orb']/df['V_p']# en sdf['T_jours']=df['T']/(24*3600)# en jours terrestresdf
Autres méthodes (compléments)
Importer les données d’une liste ou d’un dictionnaire python
Les données relatives à la planète peuvent être mises dans une liste dont l’ordre pourrait être par exemple:
Remarque: On peut ajouter plusieurs planètes dans la liste, avec par exemple: pd.DataFrame([planete1,planete2,...])
On peut alors ajouter les 2 Dataframes dans un nouveau tableau. Il s’agit d’une opération de concaténation:
pd.concat([df1,df2],ignore_index=True)
Remarques:
le premier paramètre de la fonction doit être un itérable: toujours mettre la ligne entre []
Les tableaux concaténés peuvent avoir des nombres de colonnes différents. La valeur placée dans le tableau est alors NaN. Cette valeur peut être modifiée par la suite.
le paramètre ignore_index = True permet de recréer une numérotation de l’index et eviter les doublons. Dans l’exemple proposé ici, cela permet d’eviter d’avoir 2 lignes avec l’index 0.
fusionner des tableaux aux etiquettes différentes
Les tableaux doivent avoir les mêmes etiquettes de colonne si on veut ajouter leur ligne l’une sous l’autre. Dans le cas contraire, il faudra renommer les colonnes.
Un cours de niveau débutant sur les fonctions se trouve à la page suivante: Lien
Les fonctions permettent de rendre le script plus efficace, plus facile à lire et à vérifier. Une bonne pratique est de faire régulièrement du remaniement de son code : c’est-à-dire ré-écrire les parties du programme qui fonctionnent et les mettre dans une fonction ou un module. Cela évite aussi les répétitions. On remplace alors le code par un appel à une fonction.
Généralités
Tous les langages de programmation fournissent un large ensemble de fonctions prêtes à être utilisées. Nous avons déjà rencontré diverses fonctions prédéfinies, de la librairie standard : print, input, range, len.
Définition : Une fonction est un bloc de code auquel on donne un nom en vue de le réutiliser. L’appel de son nom exécute tout le bloc de code que cette fonction contient.
Pour créer une fonction, il faut la définir avec le mot clé def, suivi du nom de la fonction, d’une paire de parenthèses suivies de :.
Return
La fonction peut retourner une valeur. Celle-ci est alors mise après le mot clé return.
defsalut():"""Accueillir tout le monde"""return'bonjour tout le monde'
On appelle cette fonction à l’aide de son nom, suivi des parenthèses :
salut()# retourne (et affiche) 'bonjour tout le monde'
Fonction python et fonction mathématique
On peut programmer une fonction pour qu’elle retourne la valeur y = f(x).
Exemple: soit la fonction mathématique $f : x \mapsto 3x^2+2$
Le script python correspondant sera:
deff(x):return3*x**2+2
Pour exécuter la fonction avec x=5, on fait: f(5)
Et cela retourne … $3\times 5^2+2$, soit 77.
Le mot-clé return joue, dans le script, un rôle analogue à celui du signe = dans l’écriture mathématique $y = f(x)$.
Docstring
Il est d’usage, dans les bonnes pratiques, d’ajouter une chaîne de documentation, à la première ligne de la fonction : le Docstring.
Le Docstring est accessible à l’aide de la fonction help :
defsalut():"""Accueillir tout le monde"""return'bonjour tout le monde'>help(salut)# afficheHelponfunctionsalutinmodule__main__:salut()Accueillirtoutlemonde
Pour plus d’informations sur le Docstring, et principalement le Prototypage, consulter la page mise au point
Passage d’argument
Définitions
Un paramètre est une information dont la fonction a besoin pour s’exécuter.
Un argument est une valeur transmise à une fonction.
Les paramètres sont placés à l’intérieur des parenthèses dans la définition de la fonction.
defsalut(nom):"""Accueillir tout le monde par son nom"""returnf'bonjour {nom}'
Lors de l’appel de la fonction, on place l’argument entre parenthèses :
La portée des paramètres et des variables déclarées dans la fonction est limitée à la fonction elle-même. Ce sont des variables locales.
externes
Les variables déclarées dans le main sont accessibles à l’intérieur d’une fonction, en lecture.
Pour les modifier depuis l’intérieur de la fonction, deux cas se distinguent :
si la variable désigne un objet mutable (une liste, un dictionnaire…), on peut modifier son contenu par un effet de bord, sans rien déclarer de particulier ;
pour réaffecter la variable elle-même — qu’elle soit mutable ou non — il faut la déclarer explicitement avec le mot-clé global à l’intérieur de la fonction (voir le cours sur les types construits, qui détaille ce mécanisme).
Lorsqu’une fonction a besoin de plusieurs valeurs, ces dernières doivent correspondre aux paramètres qu’elle attend. Les arguments doivent être placés dans l’ordre des valeurs reçues.
defpublier_msg(message,user):"""publier le message de l'utilisateur"""returnf'{user} : {message}'
Que l’on appelle en renseignant les 2 arguments :
publier_msg('Ok pour moi','Branda')# retourne (affiche) 'Branda : Ok pour moi'
Rq : il existe aussi la possibilité d’utiliser des arguments non positionnés, et nommés: voir ci-dessous.
Arguments non positionnés
On peut appeler la fonction avec des arguments non positionnés, mais, alors, il faudra nommer les paramètres. Par exemple, ici, on inverse la position des arguments, mais comme ceux-ci sont nommés, l’affectation aux paramètres est bien respectée:
defservir_cafe(client,nombre):"""servir le nombre de cafés voulus au client"""returnf'{client} commande {nombre} café(s)'>servir_cafe(nombre=10,client="Fred")'Fred commande 10 café(s)'
Valeur par défaut
Définir la valeur par défaut d’un paramètre dans une fonction permet à l’appel de la fonction d’utiliser cette valeur, sauf si une autre valeur est spécifiée à l’appel.
Lorsqu’il y a plusieurs arguments, il faudra mettre le-s paramètre-s avec valeur-s par défaut à la fin :
defservir_cafe(client,nombre=1):"""servir le nombre de cafés voulus au client"""returnf'{client} commande {nombre} café(s)'
Exemple d’utilisation :
servir_cafe('George')# on utilise la valeur du paramètre par defaut = 1# retourne 'George commande 1 café(s)'servir_cafe('Jean',2)# cette fois, on précise la valeur 2# retourne 'Jean commande 2 café(s)'
Spécifier une fonction
On a vu que pour déclarer et construire une fonction, il faut:
déclarer le nom de la fonction et ses eventuels paramètres après la commande def
placer les paramètres entre (), dans un ordre précis
terminer la première ligne, def ...: par 2 points :
indenter le bloc de code de la fonction
placer eventuellement un commentaire, à partir de la première ligne du bloc de la fonction, sur une ou plusieurs lignes, afin de préciser son comportement: """commentaire sur plusieurs lignes"""
finir par une eventuelle valeur de retour, après le return
On peut aller plus loin dans ce que l’on appelle la spécification de la fonction, en utilisant des annotations de type:
Depuis Python 3.5, on peut préciser, dans la définition d’une fonction, le type attendu pour chaque paramètre ainsi que le type de la valeur renvoyée. On parle d’annotations de type (type hints).
Ces annotations rendent la fonction plus facile à comprendre et à utiliser correctement (on sait, sans lire le corps de la fonction, ce qu’elle attend et ce qu’elle renvoie). Elles sont également exploitées par des outils externes (éditeurs de code, vérificateurs de type comme mypy) pour détecter des erreurs avant l’exécution.
Attention, piège classique : ces annotations sont purement indicatives. Python ne les vérifie pas et ne convertit pas automatiquement les arguments reçus vers le type annoncé.
f(5)# affiche 77 (un int, pas un float !)
Rien n’empêche d’appeler f avec un entier alors que x est annoté float : aucune erreur, aucune conversion, le calcul se fait simplement avec la valeur reçue. L’annotation est une indication à l’intention du programmeur (et des outils d’analyse), pas une contrainte imposée par l’interpréteur.
On peut combiner une annotation de type avec une valeur par défaut :
defservir_cafe(client:str,nombre:int=1)->str:"""servir le nombre de cafés voulus au client"""returnf'{client} commande {nombre} café(s)'
Pour aller plus loin : les annotations d’une fonction sont accessibles via son attribut __annotations__, un peu comme le Docstring est accessible via help :
Vérifier réellement les préconditions : assert et raise
Puisque les annotations de type ne sont pas contrôlées par Python, il faut, si l’on veut réellement garantir qu’une fonction reçoit des arguments valides, écrire ce contrôle soi-même. Deux outils permettent de le faire, avec un usage différent.
assert vérifie qu’une condition est vraie, et interrompt le programme avec une AssertionError si ce n’est pas le cas :
defdouble(x:int)->int:assertisinstance(x,int),"x doit être un entier"returnx*2double(2.5)# AssertionError: x doit être un entier
assert est surtout destiné à vérifier des conditions qui ne devraient jamais être fausses si le programme est correct — des invariants internes, utiles pendant le développement et les tests. Un détail important : les instructions assert peuvent être désactivées globalement au lancement de Python (option -O), auquel cas elles ne sont plus exécutées du tout. Il ne faut donc jamais s’appuyer sur assert pour une vérification qui doit rester active en toutes circonstances, en particulier pour valider une donnée saisie par un utilisateur.
raise lève explicitement une exception, d’un type que l’on choisit, et reste toujours actif, quelles que soient les options de lancement.
Dans l’exemple suivant, j’utilise la fonction isinstance pour verifier si x (le premier argument de la fonction) est de type int, (le 2e argument):
defdouble(x:int)->int:ifnotisinstance(x,int):raiseTypeError("x doit être un entier")returnx*2double(2.5)# TypeError: x doit être un entier
En résumé : on préfère assert pour des vérifications de mise au point (aides au débogage, à retirer mentalement de la logique du programme), et raise pour valider de façon fiable les entrées d’une fonction destinée à être réellement utilisée — par exemple par d’autres personnes, ou dans un programme final. La fonction isinstance(objet, type), qui renvoie True si objet est bien une instance de type, est l’outil le plus courant pour ce genre de vérification.
Importer des fonctions
Modules : fonctions dans un fichier séparé
Une fonction peut être placée dans un autre fichier. On a alors:
un fichier principal (le programme main)
un ou plusieurs fichiers annexes (modules)
Ces fonctions ne deviennent accessibles que si on les importe.
Utiliser le mot clé import pour importer un module et accéder à toutes ou partie de ses fonctions.
Le programme principal doit alors faire référence aux modules.
On utilise l’une des 3 manières proposées ci-dessous:
importmodulefrommoduleimport*importmoduleasalias
Il est préconisé de ne charger que les fonctions utiles du module:
frommoduleimportfonction
La manière avec laquelle on utilise la fonction dépend de l’import du module.
import d’une fonction d’un module et on lui donne un alias
import package1.module1
u = package1.module1.carre(a)
import d’une partie du package (le dossier)
Modules
Dans un projet plus grand, les fonctions peuvent être mises dans des modules (des fichiers séparés). On doit alors les importer pour bénéficier d’une extension du langage. Certains modules très utiles: math, turtle, random, …
Tout fichier Python peut être importé. C’est particulièrement facile lorsque les fichiers sont dans le même répertoire. Supposons que A.py et B.py le soient, on peut mettre dans B.py l’instruction from A import * : toute fonction (ou variable) déclarée dans A.py sera alors utilisable dans B.py.
if __name__ == "__main__"
Cette syntaxe idiomatique de Python permet de n’exécuter du code présent dans un fichier/module que si ce fichier/module est directement exécuté. Ce code N’est PAS exécuté lorsque ce fichier/module est importé. Cette approche est généralement utilisée pour inclure du code de test dans un module.
defma_fonction():...if__name__=="__main__":# Ce bloc n'est exécuté que si on lance ce fichier, pas s'il est importé depuis un autre modulema_fonction()
Lambda fonction: fonctions anonymes
On peut avoir recours aux fonctions anonymes pour des tâches ponctuelles qui ne nécessitent pas la création d’une fonction complète.
La syntaxe est la suivante:
lambda arguments : expression
Les arguments sont les paramètres de la fonction et l’expression calcule la valeur de retour.
Remarquez l’absence d’utilisation du mot-clé return, contrairement à une fonction classique.
Exemple:
>>>square=lambdax:x**2>>>square(2)4
Les fonctions lambda peuvent être utilisées pour trier une liste selon une clé spécifique: doc officielle
La connaissance des algorithmes suivants est exigée pour les étudiants en NSI. Le langage python propose des fonctions pour chacun d’eux. Mais, parfois, il est demandé à l’étudiant d’écrire ou compléter le script pour ces fonctions.
Parcours séquentiel
On parcourt la structure élément par élément, du début à la fin.
algorithmes de recherche
Exemple avec une liste, avec un dictionnaire
# liste : renvoie l'indice de la valeur, ou -1 si absentedefrecherche_liste(liste,valeur):foriinrange(len(liste)):ifliste[i]==valeur:returnireturn-1# dictionnaire : renvoie la clé associée à la valeurdefrecherche_dict(d,valeur):forcleind:ifd[cle]==valeur:returnclereturnNone
S’applique uniquement sur une liste triée. On compare la valeur cherchée à l’élément central puis on réduit la zone de recherche de moitié à chaque étape.
Exemple :[5, 2, 4, 1] → [1, 2, 4, 5] (le 1 puis le 2 sont placés successivement en tête)
A retenir : les deux algorithmes ont une complexité en O(n²) dans le pire des cas.
Algorithmes avancés
Algorithme glouton
A chaque étape, on fait le choix qui semble le meilleur sur le moment, sans revenir en arrière. Ne donne pas toujours la solution optimale, mais est simple et rapide.
Exemple classique : le rendu de monnaie. On utilise toujours la plus grande pièce/billet possible.
defrendu_monnaie(a_rendre,pieces):pieces.sort(reverse=True)# du plus grand au plus petitresultat=[]forpinpieces:whilea_rendre>=p:resultat.append(p)a_rendre-=preturnresultat
Limite : avec un système de pièces mal choisi, le glouton peut ne pas être optimal (ex. rendre 6 avec [4, 3, 1] donne 4+1+1 au lieu de 3+3).
Recherche des K plus proches voisins
Pour classer une nouvelle donnée, on calcule sa distance à toutes les données connues, puis on regarde les k voisins les plus proches : la classe majoritaire parmi eux devient la prédiction.
frommathimportsqrtdefdistance(p1,p2):returnsqrt((p1[0]-p2[0])**2+(p1[1]-p2[1])**2)defk_plus_proches_voisins(donnees,nouveau_point,k):# donnees : liste de (point, classe)distances=[]forpoint,classeindonnees:distances.append((distance(point,nouveau_point),classe))distances.sort()k_voisins=distances[:k]classes=[classefor_,classeink_voisins]returnmax(classes,key=classes.count)# classe majoritaire
Exemple :donnees = [((1,1), "A"), ((2,1), "A"), ((5,5), "B")] puis k_plus_proches_voisins(donnees, (1,2), 2) → "A" (les 2 voisins les plus proches sont de classe A)
A retenir : le choix de k est important — trop petit, sensible au bruit ; trop grand, mélange des classes éloignées.
fichiers Entrees/Sorties
Entrées/Sorties en console
Sortie en console
La fonction print permet l’affichage d’une valeur en console, quel qu’en soit le type.
On peut afficher un texte simple, ou composé de plusieurs parties, par concaténation de chaine :
clan = 'Vikings'
message = 'Fight Invaders'
print('We are the ' + clan + ' who say' + ' "'+ message + '!"')
# affiche
# We are the Vikings who say "Fight Invaders!"
Le problème de cette méthode de concaténation est que chaque partie composant la chaine doit être de type str. Cela est possible avec la fonction str(variable, mais il existe une méthode plus efficace : formater la chaine.
La méthode str.format() sur les chaines de caractères :
La methode de base :
clan = 'Vikings'
message = 'Fight Invaders'
print('We are the {} who say "{}!"'.format(clan, message))
# affiche
# We are the Vikings who say "Fight Invaders!"
On peut aussi préciser le nombre de caractères ou de chiffres attendus, le type de données, etc.
Cela permet d’aligner des chaînes dans une largeur de taille fixe.
Entrées au clavier : input
La fonction input met le programme en pause et attend que l’utilisateur entre une donnée.
nom=input('Quel est votre nom ? ')print('Bonjour, {}'.format(nom))
Toutes les données saisies sont converties en chaîne. Il est donc necessaire de convertir les données numériques dans le type approprié avant de les utiliser :
prix=input('Combien coute ce camion ?')prix=float(prix)ifprix<10000:print('Ok, je le prends.')
Lire le contenu d’un fichier
Repertoire courant
Selon l’IDE python choisi, vous pouvez avoir des difficultés pour ouvrir un fichier. L’interpreteur peut considérer que le repertoire courant n’est pas celui du fichier en cours d’execution, et ne trouve pas votre fichier data, qui se trouve dans le même dossier.
Pour resoudre ce problème, vous pouvez ajouter les lignes suivantes:
chdir: changer de repertoire courant pour le chemin utilisé par l’interpreteur
getcwd: chemin du repertoire courant
listdir: contenu du repertoire courant
Fichier txt
On utilise la fonction open de la librairie standart en python:
La fonction open crée donc un fichier. Elle renvoie un objet de la classeTextIoWrapper. Par la suite, nous allons utiliser des méthodes de cette classe pour interagir avec le fichier. Il existe 2 méthode pour utiliser open:
méthode 1: fonctions open et close. On créé un objet qui sert à importer le fichier. Choisir un nom quelconque, pour l’exemple qui suit ce sera file. On utilise la fonction open avec pour paramètres, le nom du fichier (son chemin), suivi du caractère ‘r’ (pour read, ouverture du fichier en lecture).
On peut alors récuperer le contenu textuel du fichier à l’aide de la méthode read. Dans l’exemple ci-dessous, on place le texte du fichier dans la variable texte.
On peut traiter cette variable comme on le souhaite, l’afficher en entier (print(texte)), ou parcourir et traiter les caractères les uns après les autres (for c in texte: ...)
Penser alors à fermer le fichier de lecture: file.close()
Le programme suivant est équivalent à celui de la méthode 1. Avec le mot clé with, les instructions de lecture du fichier sont mis dans un bloc, et donc indentées. A la sortie de ce bloc, le fichier est automatiquement fermé, ce qui fait l’economie de l’instruction close, et evite les oublis…
Exemple de programme : lire un fichier .txt avec un seul mot par ligne, et créer une liste mots
# initialisation de la liste videmots=[]# Lecture du fichier txt et remplissage de la listewithopen('liste_francais.txt',encoding='iso-8859-1')asf:formotinf.read().splitlines():mots.append(mot)
open : renvoyer un objet TextIOWrapper
as : « en tant que »
Le mot-clé with permet de créer un “context manager” (gestionnaire de contexte) qui vérifie que le fichier est ouvert et fermé, même si des erreurs se produisent pendant le bloc.
Certains caractères sont fort utiles lors de l’écriture de fichiers texte afin d’organiser les données. Le symbole ; est très utilisé comme séparateur de colonnes pour une matrice, on utilise également le passage à la ligne ou la tabulation. Comme ce ne sont pas des caractères « visibles », ils ont des codes :
\ caractère d’echappement (par exemple pour écrire des guillemets dans une chaine)
\n : passage à la ligne
\t : tabulation, indique un passage à la colonne suivante dans le format tsv (Tabulation-separated values).
Lors de la lecture d’un fichier, on peut avoir besoin de supprimer ces caractères spéciaux:
table=[]# Lecture du fichierwithopen('datas/rne-cm.csv',encoding='utf-8')asf:forlineinf.read().splitlines():table.append(line)table[2]# affiche'32\tGers\t\t\t32249\tMauvezin\tPASCOLINI\tJean-Marc\tM\t'print(table[2])# affiche32Gers32249MauvezinPASCOLINIJean-MarcMlen(table[2])# affiche 1
L’import des données n’a pas placé les valeurs comme des éléments de liste. Il faudrait découper la chaine de caractères au niveau des espaces:
On peut alors remplacer l’instruction table.append(line) par table.append(line.split('\t')), ce qui découpe la chaine au niveau des \t:
méthode 1: fonctions open et close. On créé un objet qui sert à désigner le fichier. Choisir un nom quelconque, pour l’exemple qui suit ce sera fileout. On utilise la fonction open avec pour paramètres, le nom du fichier (son chemin), suivi du caractère ‘w’ (pour write, ouverture du fichier en écriture).
On peut alors placer du texte dans le fichier à l’aide de la méthode write: fileout.write("...")
Penser alors à fermer le fichier de lecture: fileout.close()
fileout=open('exemple.txt','w')fileout.write("Je sais ta passion, et suis ravi de voir\nQue tous ses mouvements cèdent à ton devoir ;")fileout.close()
On peut alors vérifier le fichier et son contenu en parcourant le dossier avec l’explorateur windows.
méthode 2: système d’instructions with + open
Le programme suivant est équivalent à celui de la méthode 1. Avec le mot clé with, les instructions de d’écriture dans le fichier sont mis dans un bloc, et donc indentées. A la sortie de ce bloc, le fichier est automatiquement fermé, ce qui fait l’economie de l’instruction close, et evite les oublis…
withopen('exemple.txt','w')asfileout:fileout.write("Je sais ta passion, et suis ravi de voir\nQue tous ses mouvements cèdent à ton devoir ;")
à la ligne 2 : ouverture du fichier zoo2.txt en mode écriture, avec le caractère w pour write.
Si nous ouvrons le fichier zoo2.txt avec un éditeur de texte, voici ce que nous obtenons :
poissonabeillechat
Ce n’est pas exactement le résultat attendu. Le script peut être amélioré en utilisant une écriture formatée, comme vu plus haut, à la dernière ligne du script :
filout.write("{}\n".format(animal))
Ce qui donne maintenant, à l’ouverture du fichier :
convertir les données en chaine de caractère formatée:
descripteurs=['courant','tension','puissance']datas=[[0.100,2.00,0.200],[0.200,4.00,0.400]]tab=""fortitleindescripteurs:# ajout des descripteurs en tete du tableautab=tab+title+','foriinrange(len(datas)):# saut de lignetab=tab+'\n'forjinrange(len(datas[0])):tab=tab+datas[i][j]+','
Il peut être utile de sauvegarder des données en cours de travail, comportant des paramètres que l’on veut retrouver lors d’une prochaine session de travail.
Utiliser le module pickle pour écrire, puis lire une structure de donnée python, comme un dictionnaire ou une liste:
Les epreuves pratiques proposent de nombreux exemples de traitement de données en liste de dictionnaires. Se référer aux sujets de 2026.
Open Datas, liste de listes
Un exemple de données ouvertes
Plateforme ouverte des données publiques françaises
Le Répertoire National des Élus (RNE) a pour finalité le suivi des titulaires d’un mandat électoral. Il est renseigné et tenu à jour par les préfectures et hauts commissariats et par les services du ministère de l’intérieur, notamment sur la base des éléments fournis par les élus lors de la phase d’enregistrement des candidatures.
Données du RNE pour les conseillers municipaux - extrait en csv
Les données du RNE sont structurées par mandat. Neuf fichiers sont publiés ici :
les membres des assemblées des collectivités à statut particulier ;
les représentants au Parlement européen ;
les sénateurs ;
les députés ;
les maires.
En bas de page, vous pourrez observer les réutilisations de ces documents:
exemples de réutilisation des données ouvertes sur les elus municipaux
Ouvrir les données jugées d’intérêt public, c’est encourager leur réutilisation par tout un chacun. Cela permet d’encourager la transparence démocratique, de bénéficier de services au quotidien ou de prendre des décisions plus éclairées.
Ouvrir un nouveau notebook, ou bien un nouveau fichier dans votre IDE python (Spyder ou Pyzo). Déplacer le fichier *.csv dans le même dossier que le notebook/fichier python.
Lire et stocker le contenu du fichier dans une liste python que vous appelerez table.
On pourra s’aider:
du dernier paragraphe de la page Python les bases > entrées / sorties pour importer le fichier csv.
du TP sur les algorithmes de recherche dans un dictionnaire: voir TP ici
Une fois la liste des élus importée dans une liste python:
Dans votre editeur python, explorer la liste table pour qu’elle affiche les informations sur la longueur, sur les premiers élus.
Si vous choisissez le bon caractère de séparation des données, vous devriez obtenir quelque chose d’approchant (la mise à jour est régulière, et les données peuvent différer):
Question 1: Quels sont les rangs auxquels se trouvent le numero de departement, ainsi que celui du sexe de l’élu ‘H’/‘F’?
Explorer pour définir l’ordre dans lequel sont classés les élus.
Fonction recherche
Ecrire une fonction recherche qui recherche le premier élu dans un departement donné. La fonction recherche aura pour seul argument la variable textuelle dpt correspondant au departement recherché.
Cette fonction prend les éléments du tableau un par un, en commençant par le debut, et recherche la premiere occurence (le premier élu de ce departement).
Par exemple:
>recherche('06')363891
Question 2: Pourquoi la fonction retourne t-elle un entier (par exemple 363891)?
Question 3: Quelle est le numero de ligne du dernier élu du departement 06 (utiliser la fonction recherche)?
Fonction pariteHF
Ecrire une fonction pariteHF qui compte le nombre d’élus Hommes et le nombre d’élues Femmes pour un departement donné. La fonction renvoie alors le couple de valeurs H/F.
Représenter alors cette parité dans votre notebook sur un diagramme circulaire.
On s’aidera du lien suivant pour représenter des diagrammes avec Matplolib.
exemple de diagramme sur la proportion des élus H/F
Prolongement
Rechercher si, pour l’un des departements, le ratio ‘F’/‘M’ est supérieur à 1.
Faire un compte rendu avec les réponses, les scripts et graphiques. Utiliser un editeur de texte.
Suggestion de projet
Utiliser une API en python avec le module request, et charger directement le fichier de données. Une API est une interface logicielle qui permet de se « connecter » à un service, ou un serveur.
Cette méthode permet de consulter la version la plus recente, mise à jour sur le serveur. On peut imaginer de nombreuses applications (météo, prix du carburant, …)
graphique avec matplotlib
Tracé de graphiques avec curseur
La documentation complète de matplotlib.pyplot: Lien
module: D’abord importer le module:
importmatplotlib.pyplotasplt
Curseur: Ajouter Cursor si vous avez besoin de faire un relevé sur le graphique:
frommatplotlib.widgetsimportCursor
Script minimal: voici un exemple de tracé de 2 courbes superposées:
l’une de type nuage de points scatter (points non reliés)
%matplotlib qt va détacher le graphique du flux du notebook, et permettre d’utiliser le curseur (fenêtre graphique qt)
La fonction gca permet de gérer les axes et curseur.
La fonction clf permet d’effacer la figure courante et de remettre les réglages graphiques à zero.
grid pour afficher une grille
legend pour ajouter un encadré avec la légende (les labels)
regression lineaire
Regression linéaire
Principe
La regression linéaire consiste à déterminer une fonction y = a.x + b dans un nuage de points (x,y), à condition que ceux-ci semblent suffisament alignés. Cette fonction permettra alors de faire des prédictions sur la valeur y selon celle de x.
Exemple de données brutes
Commencer par importer les données de l’exemple 1: datas.csv
Placer le fichier dans le même dossier que votre fichier de travail, que vous appelerez regression.py
Vérifier la nature des données importées en affichant les premières lignes:
>>>table[:10]
Dans ce premier exemple, nous allons travailler sur une partie des données. Celles-ci ne contiennent que des informations numériques. On limite le traitement aux 90 premieres valeurs:
Voir maintenant l’allure en traçant le graphique (x,y): (méthode vue ici)
importmatplotlib.pyplotaspltplt.clf()axes=plt.gca()plt.scatter(x,y,color='silver',marker='.',label='Signal brut')plt.grid(True,which='both')plt.xlim(0,100)plt.ylim(0,5)plt.legend(loc='best')plt.title('Signal avec bruit')plt.show()
Questions: Les points présentent-ils un certain alignement? Sur quelle-s partie-s de la courbe bruitée?
Mettre en place la regression linéaire
On commence par definir le modèle mathématique. Ici, celui d’une application affine.
deffit_func(x,a,b):returna*x+b
La regression linéaire consiste à calculer les valeurs des coefficient a et b. C’est l’outil scipy_optimize.curve_fit qui va ajuster les coefficients de regression, sur le nuage de points selectionnés.
from scipy.optimize import curve_fit
# placer des valeurs dans les coefficients a et b
a = 0
b = 0
borne_inf = ??
borne_sup = ??
# calculer les parametres
params, mcov =curve_fit(fit_func,x[borne_inf:borne_sup],y[borne_inf:borne_sup])
a = params[0]; b=params[1]
Pour que l’exemple fonctionne, il faudra placer des valeurs pour les bornes inferieures et superieures, par exemple:
borne_inf=0borne_sup=90
Une fois que le programme a calculé ces coefficients, remplir une liste Y_fit avec les valeurs de regression. On utilise bien sûr la fonction du modèle, fit_func:
Y_fit=[]
for i in range(borne_inf,borne_sup):
Y_fit.append(fit_func(x[i],a,b))
Il reste à verifier la qualité de la regression en affichant:
le nuage de points (x,y)
la courbe modélisée (x[borne_inf:borne_sup],Y_fit)
plt.clf()axes=plt.gca()plt.scatter(x,y,color='silver',marker='.',label='Signal brut')plt.grid(True,which='both')plt.xlim(0,100)plt.ylim(0,5)plt.legend(loc='best')plt.title('Signal avec bruit')plt.plot(x[borne_inf:borne_sup],Y_fit,color='red',label='courbe fit')plt.show()
Application
On va appliquer le traitement sur une autre partie du nuage de points. Les données simulent le cours d’un actif numérique sur plusieurs jours:
x: numéro du jour, sur plus d’une année (500 jours?)
y: valeur de l’actif en dollards
Utiliser le même fichier datas.csv, que vous allez cette fois exploiter en entier.
La valeur montre des fluctuations quotidiennes, mais aussi un premier maximum obtenu après 90 jours. Il s’agit de ce que l’on nomme un ATH, ou “All time high”, qui désigne le pic historique d’un actif financier.
exemple de courbe montrant plusieurs ATH - www.blog.bim.finance
La fin du relevé montre une nouvelle tendance haussière. C’est sur cette dernière partie du nuage de points que vous allez faire une regression linéaire.
Utiliser la courbe de regression linéaire pour faire une prediction: quel sera le jour où la valeur de l’actif sera le même que lors de son précédent ATH?
sql et python
Base de données exoplanetes.db
Principe
Nous allons utiliser un script Python pour nous connecter à la base de données exoplanetes.db et tester quelques requêtes en langage SQLite.
Nous utiliserons la librairie sqlite3 de Python.
Il est conseillé d’utiliser l’IDE Spyder, ou bien Jupyter Notebook pour editer et interpréter les scripts écrits en Python.
La base de données doit être téléchargée ici : exoplanetes.db
extrait de la base de données
Script de base
importsqlite3try:conn=sqlite3.connect('exoplanetes.db')cur=conn.cursor()print("Base de données crée et correctement connectée à SQLite")sql="SELECT sqlite_version();"cur.execute(sql)res=cur.fetchall()print("La version de SQLite est: ",res)exceptsqlite3.Erroraserror:print("Erreur lors de la connexion à SQLite",error)cur.close()conn.close()print("La connexion SQLite est fermée")
Voici la traduction de ce script en langage naturel:
essayer:connexionalabasededonneesexoplanetes.dbcreationduncurseurSQLAfficher("Base de données cree et correctement connectee à SQLite")executerlarequeteSQL"SELECT sqlite_version();"affecterleresultatdelarequêtedanslavariableressiuneerreursurvient:Afficher("La version de SQLite est: ",sqlite3.Error)sinon:# autres requetes SQLfermetureducurseurfermeturedelaconnexionAfficher("La connexion SQLite est fermée")
Explorer la base de données
L’instruction suivante permet d’explorer la base de données:
"PRAGMA table_info(planetes_es);"
Q1. Ajouter cette requête à votre script python pour afficher les attributs de la table planetes_es de la base de données exoplanetes.db
On peut améliorer la présentation des résultats, et mettre la table retournée dans un dataframe. On utilise alors la liste L des attributs (question précédente). Voir tuto dataframe
# Toutes les données relatives aux étoiles dont le nom commence par Kepler-89importnumpyasnpimportpandasaspdsql="select * from planetes_es where _name like 'Kepler-89%'"cur.execute(sql)res=cur.fetchall()df=pd.DataFrame(res,columns=L)df
Et pour obtenir une vue avec certaines colonnes:
sql="select _name,mass,radius from planetes_es"cur.execute(sql)res=cur.fetchall()df=pd.DataFrame(res,columns=['_name','mass','radius'])df
On peut souhaiter éliminer les lignes pour lesquelles les renseignements ne sont pas complets (lignes avec Nan):
df.dropna(how='any',inplace=True)
Et ajouter des colonnes au dataframe, comme par exemple le calcul de la masse volumique de la planète: (attention, les valeurs de la table sont referencées à celles de Jupiter)
Q4. Cette base est-elle bien modélisée, respecte t-elle bien les contraintes d’intégrité vues en cours? Pq?
Q5. Tester quelques unes des requêtes sur cette base. Par exemple:
Toutes les données relatives à l’étoile Kepler-89 b
Tous les noms des planètes dont la masse est plus de 10 fois supérieure à celle de Jupiter (Indiquer quelles sont ces planètes dans l’extrait de la table)
Les planètes ainsi que le nom de l’étoile hôte, dont l’étoile est située à moins de 40 pc de la Terre.
Les noms des 20 étoiles les plus proches de la Terre où des planètes ont été détectées.
Nombre total de planètes dans la table (utiliser COUNT(*))
Nombre total d’étoiles dans la table (utiliser COUNT(DISTINCT ... ))
Table des planètes qui n’ont été détectées ni par “Radial Velocity”, ni par “Primary Transit”
Le nombre de planètes qui n’ont été détectées ni par “Radial Velocity”, ni par “Primary Transit”
Moyenne des distances entre le Soleil et les différentes étoiles de la table (utiliser AVG). Attention à ne compter qu’une seule fois chacune des étoiles.
Table des planètes où le type de l’étoile est G … (utiliser LIKE "G%")
Nom des planètes et distances au soleil, où de l’eau a été détectée (utiliser LIKE)
Etude graphique
La recherche de dépendances entre grandeurs se fera en traçant un graphique, avec différents essais pour les axes x,y: On peut chercher par exemple la dépendance masse volumique <-> rayon:
%matplotlibqtplt.clf()axes=plt.gca()x=df['radius']y=df['rho']z=df['_name']plt.scatter(x,y,color='silver',marker='.',label='Rho')# ajout d'une etiquetteforx,y,zinzip(x,y,z):axes.text(x,y,f"({z})",fontsize=8)cursor=Cursor(axes,useblit=True,color='red',linewidth=2)plt.show()
Superposer les données des exoplanètes découvertes par TOI-270 avec la BDD
Commencer par selectionner et nettoyer les données issues de la base de données:
# BDD - Toutes exoplanetessql="PRAGMA table_info(planetes_es);"cur.execute(sql)res=cur.fetchall()L=[ligne[1]forligneinres]sql="select * from planetes_es"cur.execute(sql)res=cur.fetchall()df0=pd.DataFrame(res,columns=L)# table entieredf0=df0[['_name','orbital_period','radius']]# projection sur les colonnes utilesdf0.dropna(how='any',inplace=True)# retirer les lignes avec datas non renseignéesdf0
importer et traiter les données issues des observations
Cette partie est détaillée à la page données en dataframe
df=pd.read_csv('donnees_planetes.txt',sep=';')G=6.67e-11R_Jup=71e6M_Jup=6.9911e7df['tau']=(df['fin_transit']-df['debut_transit'])*24*3600df['delta']=1-df['lum_min']df['M_star']=7.158780e+29df['R_star']=257512600.0df['R_p']=np.sqrt(df['delta'])*df['R_star']df['radius']=df['R_p']/R_Jup# vitesse planete : V_p = 2*R_star/taudf['V_p']=2*df['R_star']/df['tau']# rayon orbital : r = G*M_star/V_p**2df['r_orb']=G*df['M_star']/df['V_p']**2# periode revolution: T = 2*np.pi*r/V_pdf['T']=2*np.pi*df['r_orb']/df['V_p']df['T_jours']=df['T']/(24*3600)df
Tracer les 2 nuages de points
%matplotlibqtplt.clf()axes=plt.gca()"""nuage de points df issu de la BDD
"""x=df['radius']y=df['orbital_period']z=df['_name']plt.scatter(x,y,color='silver',marker='.',alpha=0.5)"""nuage de points df_p issu des observations
"""x_p=df_p['radius']y_p=df_p['orbital_period']z_p=df_p['_name']plt.scatter(x_p,y_p,color='red',marker='o',label='Rho')forx,y,zinzip(x_p,y_p,z_p):axes.text(x,y,f"({z})",fontsize=8)plt.xscale('log')plt.yscale('log')plt.xlabel('radius')plt.ylabel('orbital_period')cursor=Cursor(axes,useblit=True,color='red',linewidth=2)plt.show()
orbital_period vs radius en echelle log
Partager la fenêtre graphique en plusieurs graphiques
Travail: le script ci-dessous permet de visualiser plusieurs graphiques sur la même sortie. Adapter le script pour sélectionner les grandeurs correlées.
Vous savez placer les nouvelles exoplanètes sur un graphique en nuage de points, au milieu des autres planètes de la base de données.
Vous savez sélectionner la représentation qui donnera le plus d’informations:
exemple de représentations à partir de différents choix d'axes
Une voie d’étude serait de rechercher des clusters (regroupements) de planètes pour certains choix d’axes, et d’associer nos exoplanètes à celles-ci.
Une autre voie possible serait d’intégrer la Terre, avec toutes ses caractéristiques connues, dans la table de la base de données. On établirait alors un coefficient, appelé Indice de Similarité avec la Terre (IST), qui permettrait de trier ces planètes selon l’IST décroissant: Lien vers l’étape 5
TP exoplanets.db
PARTIE 1: Base de données exoplanetes.db
Principe
Nous allons utiliser un script Python pour nous connecter à la base de données exoplanetes.db et tester quelques requêtes en langage SQLite.
Nous utiliserons la librairie sqlite3 de Python.
Utiliser un IDE comme Pyzo, Spyder, ou bien Jupyter Notebook pour editer et interpréter les scripts écrits en Python.
importsqlite3try:conn=sqlite3.connect('exoplanets_migrated.db')cur=conn.cursor()print("Base de données crée et correctement connectée à SQLite")sql="SELECT sqlite_version();"cur.execute(sql)res=cur.fetchall()print("La version de SQLite est: ",res)exceptsqlite3.Erroraserror:print("Erreur lors de la connexion à SQLite",error)
Table planets
Pour avoir des informations sur la table:
sql="""
PRAGMA table_info(planets);
"""
try:cur.execute(sql)res=cur.fetchall()print(f"{'Attribut':<20}{'Domaine':<10}")print("-"*30)forrowinres:print(f"{row[1]:<20}{row[2]:<10}")exceptsqlite3.Erroraserror:print("Erreur lors de la connexion à SQLite",error)
Résultat:
Attribut Domaine
------------------------------
planet_id INTEGER
name TEXT
planet_status TEXT
mass REAL
radius REAL
orbital_period REAL
semi_major_axis REAL
eccentricity REAL
discovered INTEGER
detection_type TEXT
molecules TEXT
star_id INTEGER
table stars
Travail: Adapter le script précédent pour avoir les informations de la table stars
Selection avec jointure
La requête suivante va donner les informations sur les premières exoplanètes de la table, ainsi que leur étoile, avec jointure entre les 2 tables.
try:sql="""
SELECT p.name, p.mass, p.radius, s.star_name, s.star_teff
FROM planets p
JOIN stars s ON p.star_id = s.star_id
LIMIT 5;
"""cur.execute(sql)res=cur.fetchall()print(f"{'Planète':<20}{'Masse':<10}{'Rayon':<10}{'Étoile':<15}{'Teff'}")print("-"*60)forrowinres:print(f"{str(row[0]):<20}{str(row[1]):<10}{str(row[2]):<10}{str(row[3]):<15}{row[4]}")exceptsqlite3.Erroraserror:print("Erreur lors de la connexion à SQLite",error)
A Faire: Executer le script précédent pour obtenir…
Planète Masse Rayon Étoile Teff
------------------------------------------------------------
11 Com b None None 11 Com 4742.0
11 Oph b 21.0 None 11 Oph 2375.0
11 UMi b None None 11 UMi 4340.0
14 And b None None 14 And 4813.0
14 Her b None None 14 Her 5311.0
PARTIE 2: Requetes diverses sur la BDD
Explorer la base de données
Aidez vous du script précédent, que vous modifierez pour repondre aux questions ci-dessous. Sélectionnez en au moins 4.
(table stars) Toutes les données relatives à l’étoile Kepler-89 b
(table planets) Tous les noms des planètes dont la masse est plus de 10 fois supérieure à celle de Jupiter (Indiquer quelles sont ces planètes dans l’extrait de la table)
(tables planets ET stars) Les planètes ainsi que le nom de l’étoile hôte, dont l’étoile est située à moins de 40 pc de la Terre.
(tables planets ET stars) Les noms des 20 étoiles les plus proches de la Terre où des planètes ont été détectées.
(table planets) Nombre total de planètes dans la table planets(utiliser COUNT(*))
(table stars) Nombre total d’étoiles dans la table stars
(table planets) Table des planètes qui n’ont été détectées ni par “Radial Velocity”, ni par “Primary Transit”
(table planets) Le nombre de planètes qui n’ont été détectées ni par “Radial Velocity”, ni par “Primary Transit”
(table stars) Moyenne des distances entre le Soleil et les différentes étoiles de la table (utiliser AVG). Attention à ne compter qu’une seule fois chacune des étoiles.
(tables planets ET stars) Table des planètes où le type de l’étoile est G … (utiliser LIKE "G%")
(tables planets ET stars) Nom des planètes et distances au soleil, où de l’eau a été détectée (utiliser LIKE)
(tables planets ET stars) Le classement des étoiles, par ordre décroissant de leur nombre de planètes. (GROUP BY, ORDER BY). Limiter à 10 étoiles.
Traitement
Ajouter une colonne masse volumique
Travail: Commencer par créer une nouvelle colonne density dans la table planets, et afficher les attributs de cette table:
try:cur.execute(sql1)cur.execute(sql2)res=cur.fetchall()print(f"{'Attribut':<20}{'Domaine':<10}")print("-"*30)forrowinres:print(f"{row[1]:<20}{row[2]:<10}")exceptsqlite3.Erroraserror:print("Erreur lors de la connexion à SQLite",error)
Les données de la table planets sont relative à Jupiter. On rappelle que:
On peut définir une densité pour la planète comme le rapport $\tfrac{\rho_{planete}}{\rho_{Jupiter}} = \tfrac{mass}{radius^3}$.
On ajoutera simplement dans la colonne density
$$density = \tfrac{mass}{radius^3}$$
Travail: Ecrire la requête sql1 (UPDATE SET) pour calculer la density de chaque planète. Le calcul de $x^y$ peut necessiter l’ajout de la fonction power dans le langage SQL si celle-ci n’est pas implémentée (POWER):
conn.create_function("power",2,lambdax,y:x**yifx!=Noneandy!=NoneelseNone)sql1="""
UPDATE planets SET density=mass/power(radius,3)
"""
Travail: Récuperer ensuite les valeurs de la table (sql2), et afficher par ordre decroissant de densité. Executer les 2 requêtes (voir script complet ci-dessous)
Obtenir le tableau suivant avec le classement des planètes par densité décroissante:
Planète Masse Rayon Density
------------------------------------------------------------
Kepler-57 c 6.95 0.138 2644.5241987281925
Kepler-57 b 18.86 0.195 2543.5357979736677
Kepler-52 c 10.41 0.164 2360.0390301939897
Kepler-59 b 2.05 0.098 2178.0890615304843
...
On peut utiliser le script ci-dessous (compléter la requête SQL):
conn.create_function("power",2,lambdax,y:x**yifx!=Noneandy!=NoneelseNone)try:sql1="""
UPDATE planets SET density=mass/power(radius,3)
"""sql2="""
SELECT ... from planets order by ... DESC;
"""cur.execute(sql1)cur.execute(sql2)res=cur.fetchall()print(f"{'Planète':<20}{'Masse':<10}{'Rayon':<10}{'density':<15}")print("-"*60)forrowinres[:10]:# on limite la sortie à 10 planètesprint(f"{str(row[0]):<20}{str(row[1]):<10}{str(row[2]):<10}{str(row[3]):<15}")exceptsqlite3.Erroraserror:print("Erreur lors de la connexion à SQLite",error)
Etude graphique
La recherche de dépendances entre grandeurs se fera en traçant un graphique, avec différents essais pour les axes x,y.
On utilisera le resultat res de la requete precedente. C’est un tableau avec pour colonnes les nom, masse, rayon, densité.
On peut chercher par exemple la dépendance masse <-> rayon.
importmatplotlib.pyplotaspltplt.clf()axes=plt.gca()x=[P[1]forPinres]# massy=[P[2]forPinres]# radiusplt.scatter(x,y,color='silver',marker='.')plt.xlabel('mass')plt.ylabel('radius')axes.set_xscale("log",base=10);# ajout d'un marqueur "Jupiter"z="Jupiter"MJ,RJ=1,1plt.plot(MJ,RJ,marker='o',color='red')axes.text(MJ,RJ,f"({z})",fontsize=8)plt.show()
Analyser chaque partie de ce script:
(1) Que font les instructions: x = [P[1] for P in res] et y = [P[2] for P in res] ?
(2) Comment adapter ces instructions pour tracer un graphique mass/densité?
(3) Pourquoi met-on l’echelle des abscisses en logarithme: axes.set_xscale("log", base=10)?
(4) Compléter ce script pour placer un marqueur de couleur bleue à l’emplacement de la Terre. Ajouter l’etiquette “Terre”
try:sql="""
SELECT name, mass, radius from planets;
"""cur.execute(sql)res=cur.fetchall()print(f"{'Planète':<20}{'Masse':<10}{'Rayon':<10}")print("-"*60)forrowinres[:10]:# on limite la sortie à 10 planètesprint(f"{str(row[0]):<20}{str(row[1]):<10}{str(row[2]):<10}")exceptsqlite3.Erroraserror:print("Erreur lors de la connexion à SQLite",error)
Visualisation
On adoptera la visualisation des axes : x = masse (en echelle logarithmique) et y = rayon.
Pour adapter les valeurs à ce système de coordonnées, on aura besoin de la fonction suivante:
defcoordonnees_cercle_xlog_y(x_center,y_center,radius):# Cercle adapté à l'échelle logarithmiquex_center_log=np.log10(x_center)theta=np.linspace(0,2*np.pi,100)# Points du cercle en coordonnées (log(x), y)x_circle_log=x_center_log+radius*np.cos(theta)y_circle=y_center+radius*np.sin(theta)# Reconvertir x en échelle normalex_circle=10**x_circle_logreturnx_circle,y_circle
Puis, pour le tracé:
importmatplotlib.pyplotaspltimportnumpyasnpplt.clf()axes=plt.gca()x=[P[1]forPinres]# massy=[P[2]forPinres]# radiusplt.scatter(x,y,color='silver',marker='.')plt.xlabel('mass')plt.ylabel('radius')axes.set_xscale("log",base=10)# ajout d'une etiquette Jupiterz="Jupiter"MJ,RJ=1,1plt.plot(MJ,RJ,marker='o',color='red')axes.text(MJ,RJ,f"({z})",fontsize=8)# ajout d'une etiquette Terrez2="Terre"plt.plot(x_T,y_T,marker='o',color='blue')axes.text(x_T,y_T,f"({z2})",fontsize=8)# Tracer le cercle autour de la Terrex_circle,y_circle=coordonnees_cercle_xlog_y(x_T,y_T,0.3)plt.plot(x_circle,y_circle,color='gold',linewidth=1.5)plt.show()
Travail: Obtenir le graphique en nuage de points masse-rayon. Ajouter les instructions dans ce script pour tracer un autre cercle, centré autour de Jupiter.
Détermination des plus proches voisins
fonction distance_knn pour SQL
A Faire: Copier-coller la fonction suivante dans votre programme
# Distance KNN SQLdefdistance_knn_sql(x,y):"""
Calcule la distance euclidienne à la Terre dans l'espace (log(masse), rayon)
Compatible avec SQLite create_function
Parameters:
x : masse de la planète
y : rayon de la planète
Returns:
distance : distance euclidienne à la Terre (ou None si données manquantes)
"""ifxisNoneoryisNoneorx<=0:# log nécessite x > 0returnNoneimportmathx_log=math.log10(x)x_T_log=math.log10(x_T)distance=math.sqrt((x_log-x_T_log)**2+(y-y_T)**2)returndistance# Enregistrement de la fonction dans SQLiteconn.create_function("distance_knn",2,distance_knn_sql)
nouvelle colonne distance
Travail:
(1) Créer une nouvelle colonne distance_terre dans la table planets :cur.execute("""ALTER TABLE ... ADD COLUMN ...""")
(2) Ajouter le script suivant, que vous devrez compléter et executer
# Calculer la distance pour toutes les planètescur.execute("""
UPDATE planets
SET distance_terre = ... ...(mass, radius)
""")# Puis pour sélectionner les K plus proches voisinsK=5cur.execute(f"""
SELECT name, mass, radius, ... ...(mass, radius) as distance
FROM planets
WHERE ... ...(mass, radius) IS NOT NULL
ORDER BY ...
LIMIT {K}""")res=cur.fetchall()
Questions:
(1) Combien de planètes sont à l’intérieur du cercle de rayon 0.3, centré autour de la Terre?
(2) Quelle est l’exoplanète la plus ressemblante à la Terre?
on commence par créer une matrice de correlation à partir des colonnes de la table (dataframe). Aux intersections ligne/colonne on donne le résultat de la correlation entre les 2 séries (fonction corr)
puis on affiche cette matrice, en superposant des couleurs: fonction heatmap
Puis utiliser le script suivant pour superposer 2 nuages de points, dont l’un en couleur:
%matplotlibqtplt.clf()axes=plt.gca()"""nuage de points df issu de la BDD
"""x=df['radius']y=df['orbital_period']z=df['_name']plt.scatter(x,y,color='silver',marker='.',alpha=0.5)"""nuage de points df_p issu des observations
"""x_p=df_p['radius']y_p=df_p['orbital_period']z_p=df_p['_name']plt.scatter(x_p,y_p,color='red',marker='o',label='Rho')forx,y,zinzip(x_p,y_p,z_p):axes.text(x,y,f"({z})",fontsize=8)plt.xscale('log')plt.yscale('log')cursor=Cursor(axes,useblit=True,color='red',linewidth=2)plt.show()
orbital_period vs radius en echelle log
à vous de jouer
Faire un choix d’axes pertinent, afin de trouver des clusters d’exoplanètes et les comparer avec nos planètes d’étude.
Suite
Analyse, segmentation des données en clusters et previsions avec le module scikit-learn: étape 7
kmean et exoplanetes
Utiliser le module Scikit-learn
Que fait ce module?
Scikit-learn est une bibliothèque libre Python destinée à l’apprentissage automatique. Cette bibliothèque propose une série d’outils pour l’étude des données en table comme:
la regression linéaire
la classification
le clustering
…
Nous allons utiliser cette bibliothèque pour rechercher des dépendances entre les données des exoplanètes connues. Le travail de représentation graphique nous a montré que ces planètes se regroupent en clusters sur les diagrammes en nuages de points. (echelle log).
Scikit-learn va nous aider à determiner des classes d’exoplanètes (tellurique, gazeuse, similaire aux étoiles). Nous rappelons que la table dataset.csv contient les données des exoplanètes, de leurs étoiles, ainsi que les données ajoutées (Terre et système TOI_270).
Vous pouvez télécharger le dossier complet ici: sources.zip, contenant:
le fichier de dependances requirment.txt
la table dataset.csv
le notebook intro_IA.ipynb
Prérequis: Ce notebook demande d’être familiarisé avec les types np.array, et pandas.dataframe.
Apprentissage non supervisé
Les classes des astres ne sont pas renseignés dans la table dataset.csv. Pourtant, il apparait évident que ces astres se regroupent en amas, donc certainement en familles.
radius - mass en echelle log. Données issues du fichier dataset.csv
Le principe de la recherche de cluster par scikit-learn utilise la fonction kmeans de recherche de plus proches voisins. Elle peut être testé avec le script minimum ci-dessous:
importnumpyasnpfromsklearn.clusterimportKMeansimportmatplotlib.pyplotasplt# Génération de données aléatoires (non étiquetées)np.random.seed(42)data=np.random.rand(100,2)# 100 points avec 2 caractéristiques# Création et entraînement du modèle K-Meanskmeans=KMeans(n_clusters=3,random_state=42)# 3 clusterskmeans.fit(data)# Récupération des résultatslabels=kmeans.labels_# Les clusters attribués à chaque pointcentroids=kmeans.cluster_centers_# Les centres des clusters# Visualisation des clustersplt.scatter(data[:,0],data[:,1],c=labels,cmap='viridis',s=50,alpha=0.7)plt.scatter(centroids[:,0],centroids[:,1],c='red',marker='X',s=200,label='Centroids')plt.title("Clustering avec K-Means")plt.xlabel("Caractéristique 1")plt.ylabel("Caractéristique 2")plt.legend()plt.show()
exemple de resultat donné par la recherche de clusters (données aléatoires)
La fonction kmeans utilise l’algorithme de LLoyd. La recherche d’un centre de cluster (centroïd) pourrait se faire par recherche exhaustive, mais alors, la complexité serait très importante et le temps de calcul rapidement divergent avec le nombre de points. Dans cet algorithme, la recherche est basée sur un algorithme glouton. Celui-ci va chercher à minimiser une grandeur appelée inertie, qui est calculée comme la distance du centroïd à ses voisins. Enfin, les points sont segmentés en plusieurs clusters, tels que la variance est à peu près identique pour le calcul de l’inertie.
Données de la table dataset.csv
Comme dans l’activité précédente: importer les données de la table:
df_reduit=df[['mass','radius','_name']]df_reduit=df_reduit.dropna()# echelle log# rappel: les données sont normalisées par rapport à Jupiterx=np.log(df_reduit['mass'])y=np.log(df_reduit['radius'])L=[]forx,yinzip(x,y):L.append([x,y])L[:10]# Affichage --------------------[[-5.761407122499511,-2.409803828596342],[-4.567874401244395,-2.4079456086518722],[-5.0206856299497575,-2.4079456086518722],[-5.506572305368496,-2.406835114367845],[-5.8781358618009785,-2.419118909249997],[-3.101092789211817,-2.419118909249997],[-6.16581793425276,-2.372685720673535],[-5.4398809308698235,-2.3622289459215606],[-5.910806644090528,-2.3580978029243043],[-3.669469060594113,-2.4651040224918206]]# ------------------------------
Recherche de cluster par apprentissage automatisé (Kmean: recherche des plus proches voisins)
importnumpyasnpfromsklearn.clusterimportKMeansimportmatplotlib.pyplotasplt# données (non étiquetées)data=np.array(L)# Création et entraînement du modèle K-Meanskmeans=KMeans(n_clusters=3,random_state=50)# 3 clusterskmeans.fit(data)# Récupération des résultatslabels=kmeans.labels_# Les clusters attribués à chaque pointcentroids=kmeans.cluster_centers_# Les centres des clusters# Visualisation des clustersplt.scatter(data[:,0],data[:,1],c=labels,cmap='viridis',s=5,alpha=0.7)plt.scatter(centroids[:,0],centroids[:,1],c='red',marker='X',s=200,label='Centroids')plt.title("Clustering avec K-Means")plt.xlabel('mass')plt.ylabel('radius')plt.legend()plt.show()
segmentation en 3 clusters
On peut alors vérifier la valeur donnée aux 3 étiquettes (classes)
, ainsi que le nombre d’items dans chaque classe:
Superposer les exoplanètes de TOI_270 et celles de la Terre
Selection des planètes TOI_270 ainsi que la Terre dans la table dataset.csv:
names=['TOI-270 d','TOI-270 b','TOI-270 c','earth']df_p=df[df['_name'].isin(names)]"""nuage de points df_p issu des observations
"""x_p=np.log(df_p['mass'])y_p=np.log(df_p['radius'])z_p=df_p['_name']
Superposition des données de df_p:
plt.clf()axes=plt.gca()# data et labels sont calculés plus haut plt.scatter(data[:,0],data[:,1],c=labels,cmap='viridis',s=5,alpha=0.7)plt.scatter(x_p,y_p,color='red',marker='o')forx0,y0,z0inzip(x_p,y_p,z_p):axes.text(x0+0.4,y0*1.1,f"({z0})",fontsize=10)plt.xlabel('mass')plt.ylabel('radius')plt.show()
superposition des planètes du système TOI_270 et de la Terre
Prévision des classes pour les planètes de TOI_270
Prediction pour la planète Jupiter
Documentation: La fonction Kmeans du module scikit-learn
# reduction du tableau aux 2 colonnes masse et rayoncouples_xp_yp=Liste[:,:2]# predictionkmeans.predict(couples_xp_yp)# Affichage --------------------array([1,1,1,1],dtype=int32)# ------------------------------
Comme attendu d’après le graphique précedent, les 4 planètes du tableau df_p sont de classe 1. (cluster vert)
modularité
Ce chapitre comprend 2 pages de cours et une page exercices:
Un module est un fichier python (d’extension .py) contenant des fonctions.
En principe, il n’est pas prévu pour être executé. Pour faire référence aux fonctions de ce module, il faut l’importer depuis le script principal (ìmport module.py`).
Quand utiliser un module ?
Lorsque vous réalisez un projet en python, votre script s’agrandit, et vous aurez certainement le besoin de séparer votre code dans plusieurs fichiers.
Ainsi, il vous est facile de réutiliser des fonctions écrites pour un programme dans un autre sans avoir à les copier.
Mettre son programme sous forme de modules
On a vu la différentes manières d’importer un module dans le cours Python > Fonctions
On peut souhaiter, par exemple, créer une représentation graphique des nombres premiers dans une fenêtre turtle. On souhaite diviser les fonctions dans 2 fichiers:
le fichier executable (appelé le fichier main): imaginons que vous lui donniez le nom nombresPrem.py. Ce fichier ne contiendra que les fonctions relatives au calcul des nombres premiers. On y mettre aussi l’instruction qui appelera la fonction de dessin du module. C’est elle qui construira et dessinera dans la fenêtre graphique.
le fichier module de nom fcts_turtle.py qui contiendra toutes les fonctions utiles pour la représentation graphique. On supposera que ce fichier contient la fonction ulam qu’il faudra appeler pour declencher le tracé.
Le dossier contient alors:
Le fichier principal nombresPrem.py sera organisé comme ceci:
#####partie import des modules############importfcts_turtle#####variables globales##################### declaration des variables globales#######definition des fonctions############# def des fonctions du fichier main# pour le calcul des nombres premiers######corps du programme : ################### à executer si fichier main ############if__name__=='__main__':# calcul d'une liste de nombres premiers# appel de la fonction de dessin du module:fcts_turtle.ulam(liste_premiers,N)###########################################
Il est recommandé de mettre les instructions du programme principal dans un bloc avec le test if __name__=='__main__':
Ceci permet d’importer le contenu du fichier sans déclencher son execution; et permettre de realiser des tests sur les fonctions. Voir
tests sur les modules avec unittest
Le module fcts_turtle.py :
"""
DOCSTRING
"""#####partie import des modules externes###importturtle#######definition des fonctions du module## fonction de dessin de la fenêtre# fonction ulam(liste_premiers,N)##########################################
Remarque : Il est essentiel que le module comprenne un docstring BIEN documenté.
Gérer les modules
depuis le shell python
Il est possible de parcourir les dossiers du disque dur, travailler sur les fichiers, etc, comme avec un shell Unix. Depuis le notebook ou bien depuis un shell python, il faut commencer par importer le module os. Les instructions utiles sont :
listdir() pour lister
getcwd() pour obtenir le chemin (CWD = « Current Working Directory »)
chdir() pour changer de dossier
importosos.listdir()# renvoie la liste des fichiers et dossiers:['fenDestroy.py','fcts_turtle.py','tk_turtle.py','__pycache__','spirale_ulam.py','nombresPrem.py']
os.getcwd()# donne le chemin du dossier courant'/Users/nom_user/Applications/python/dessins'
os.chdir('..')# permet de remonter au dossier parentos.getcwd()# affiche '/Users/nom_user/Applications/python`os.chdir(`dessin/turtle`)# se deplacer dans un sous dossieros.getcwd()# affiche '/Users/nom_user/Applications/python/dessins/turtle`
Une différence avec le shell Unix est le traitement des noms de fichiers et dossiers qui sont mis entre guillemets. Ce sont des chaines de caracteres pour python.
Afficher le contenu et l’aide d’un module
depuis le shell python, se placer dans le repertoire contenant le module ou adapter le chemin, puis:
importer le module
lister les fonctions contenues dans le module avec dir(nom_du_module)
Rq: Notez que le fichier est bien enregistré avec une extension .py et pourtant on ne la précise pas lorsqu’on importe le module.
Et si le Docstring du module est présent:
importfcts_turtlehelp(fcts_turtle)# affiche:Helponmodulefcts_turtle:Helponmodulefcts_turtle:NAMEfcts_turtle-modulepourvisualiserlesnombrespremiersDESCRIPTIONfonctionsutilespourtracerunespiraleavecturtle.FUNCTIONSclose_window()ulam(premiers,N,L=220,h=220)representelaspiraledeUlamParams------premiers:listlesnombrespremiersN:intdernierevaleurdelaspiraleL:intdimensiondurectangleenlargeur.220pxpardefauth:intdimensiondurectangleenhauteur.220pxpardefautPrincipe--------Lesnombressontecritssurlaspirale.Enrougesilenombreestpremier,ennoirsinon.Appel-----ulam(premiers,100)# tracé de la spirale avec la liste de nombres premiers mis en argument, jusqu'à N=100.
Créer le Docstring d’un module
Un docstring est un commentaire multi-lignes utilisé pour documenter des modules, des classes, des fonctions et des méthodes. Il doit s’agir de la première déclaration du composant qu’il décrit.
Une bonne docstring de fonction doit contenir tout ce dont un utilisateur a besoin pour utiliser cette fonction. Une liste minimale et non exhaustive serait :
ce que fait la fonction,
ce qu’elle prend en argument,
ce qu’elle renvoie.
En pratique
démarrer le fichier par un commentaire multi-lignes qui documente le module
ajouter le prototype de chaque fonction selon la méthode vu dans le cours langage/mise au point
Voici un exemple de commentaire multi-lignes pour présenter le module (mis à la premiere ligne du fichier):
"""module pour visualiser les nombres premiers
fonctions utiles pour tracer une spirale avec turtle.
"""
ce qui renvoie à l’aide de la commande help(module):
Help on module fcts_turtle:
NAME
fcts_turtle - module pour visualiser les nombres premiers
DESCRIPTION
fonctions utiles pour tracer une spirale avec turtle.
FUNCTIONS
(prototype de chaque fonction)
L’infographie ci-contre montre une mesure des lignes de code dans certains programmes conséquents. Les mesures sont en millions de ligne de code:
codebase - millions lines of code visualized
On peut ajouter qu’il y a omniprésence de programmes longs dans des systèmes critiques : finance, transports, économie, santé… La moindre erreur peut coûter « cher » : on aimerait qu’un programme s’exécute correctement dans toutes les situations…
Maintenir le code, travailler en équipe demande également une certaine méthodologie.
Pour programmer en grand, c’est à dire programmer avec plusieurs fichiers, il faudra adopter les bonnes pratiques, c’est à dire:
documenter ses fonctions
procéder par étapes, en ajoutant des tests structurels pour aider au developpement
utiliser des modules pour ses fonctions et classes
tester ses fonctions, vérifier qu’elles fonctionnent correctement.
du script aux tests unitaires, une démarche de projet
En Python, pour créer une cohérence dans le code, il est recommandé d’utiliser un guide de style. Il s’agit de PEP8, présenté par exemple sur python.sdv.univ-paris-diderot.
Spécification d’un algorithme ou d’une fonction
Spécifier un algorithme signifie qu’on le décrit avec précision. On spécifie chacun des composants, structures de données et fonctions.
La documentation peut-être en consultation dans un document externe au programme (un fichier readme.md, une page sur wikipedia, …). Cette documentation peut alors fournir un pseudo-code, c’est à dire une série d’instruction avec des conventions de langages empruntées aux principaux langages existants, sans toutefois être rédigée dans un langage particulier.
Mais cela peut-être réalisé aussi au sein même du code du programme ou de la fonction. On y ajoute alors des informations facultatives lors de la déclaration de la fonction ou dans le docstring.
De manière générale, la spécification va comprendre :
Le nom donné à cet algorithme. Ce nom doit être explicite, en rapport avec la tâche effectuée par l’algorithme
Une description du résultat de cet algorithme, ainsi que la manière avec laquelle on va s’y prendre
Le type et la nature des données en entrée
Le type et la nature des données en sortie
eventuellement, le type et la nature des variables internes.
Documentation externe à l’aide d’un pseudo-code
Le pseudo langage adopté est celui utilisé dans wikipedia : exemple
Exemple de pseudo langage:recherche_du_maximum
"""
L'algorithme recherche la valeur maximale dans la liste.
variables en entrée :
------------------
:ma_liste : list, une liste de valeurs entieres, uniques, mises dans un ordre aléatoires.
:max : int, stocke la valeur maximale actuelle. Initialisé à 0.
Sortie :
------
:max : int, prend la valeur de l'élément le plus grand de la liste
Principe :
--------
on parcourt la liste avec une boucle bornée.
si la valeur la valeur de max est inferieure à la valeur courante, max est actualisée avec cette valeur courante
Exemple:
> recherche_maximum([0,2,3,1])
3
--------
"""max:=0pouriallantdupremieraudernierelementdema_listefairesii>maxmax:=ifinfinaffichermax
Nous allons adapter cette spécification, prévue pour expliquer des algorithmes, à nos fonctions écrites en python.
Documentation interne
La spécification au sein même de la fonction se fait en 2 temps:
lors de la déclaration
juste après la déclaration, dans le prototype (docstring) de la fonction.
Dans la déclaration de la fonction (prototype)
Une fonction doit être déclarée avant son utilisation. Cette déclaration est le prototype de la fonction. Le prototype doit indiquer à l’utilisateur le nom de la fonction, le type de la valeur de retour et le type des paramètres.
Pour de nombreux langages, ce prototypage est explicite, et cela provoque une erreur de compilation si ce prototypage n’est pas correct.
Exemple de déclaration d’une fonction en langage ADA :
Remarquez la difference avec la déclaration minimale suivante, qui n’apporte pas d’information sur les types:
defa_rect(larg,longueur):...
Docstring d’une fonction
En python, on pourra construire le docstring dans le commentaire, mis tout de suite après la déclaration de la fonction :
defa_rect(larg,long):"""Le produit de 2 nombres.
Renvoie le produit des 2 nombres passés en argument
:param larg : int ou float
la largeur du rectangle
:param long : int ou float
la longueur du rectangle
:return a: int ou float
larg * long
Exemple
-------
>>> a_rect(2,3)
6
"""a=larg*longreturna
Pour accéder au contenu du docstring depuis le shell python, il faudra charger le fichier: > from fichier import *, puis utiliser help:
>help(a_rect)
Pour sortir de la fenêtre de l’aide, appuyer sur la touche q.
On pourra consulter la page du site Lyceum pour plus d’informations.
Prévoir et gérer les erreurs
Gérer les erreurs: lire le Traceback
L’exécution d’un programme peut provoquer une erreur, une exception. Lorsque c’est le cas, l’exécution s’arrête immédiatement et l’interpréteur Python affiche une trace d’erreur.
Cette dernière fournit des informations quant au chemin d’exécution qui a mené jusqu’à l’erreur et sur la cause de cette dernière.
La console affiche Traceback, qui marque le début de la trace d’erreur.
L’interpréteur Python affiche ce qu’on appelle la pile d’appels ou pile d’exécution. La pile d’appel permet d’obtenir la liste de toutes les fonctions pour remonter jusqu’à celle où l’erreur s’est produite.
Les messages d’exception affichés par le Traceback.
message
type erreur
SyntaxError
parenthèse, crochet ou guillemet mal fermé
IndentationError
mauvaise indentation
ZeroDivisionError
division par zero
NameError
nom de fonction ou de variable mal orthographié
IndexError
accès à une position en dehors d’une liste
AttributeError
accès à une méthode ou à un attribut inconnu. Exemple: ’list’ object has no attribute ‘appand’
TypeError
types incompatibles pour l’opération demandée. Exemple: unsupported operand type(s) for ‘-’: ‘range’ and ‘int’
ValueError
une valeur est inappropriée pour une certaine opération
KeyError
Une clé est utilisée pour accéder à un élément d’un dictionnaire dont elle ne fait pas partie
Anticiper les erreurs: Les tests STRUCTURELS
les tests structurels, vont verifier le fonctionnement interne du programme. Leur rôle est par exemple de couvrir les différentes branches conditionnelles, les limites d’une boucle, les types de données possibles pour une opération, …
Ces tests vont aider à programmer en grand, car ils vont fournir des moyens de contrôle à différentes étapes. Ils vont aussi guider l’utilisateur de vos fonctions grâce aux messages d’erreurs et arrêts du programme.
Attention, il s’agit de trouver des erreurs, plutôt que de prouver que ça marche. C’est une validation expérimentale du programme.
On placera des pré-conditions et post-conditions autour de la fonction à tester. Ce sont des tests structurels, qui vont arrêter le programme et spécifier le type d’erreur, pour aider à debugger.
Assertions: assert
Les assertions sont les hypothèses avec vérification.
Le rajout provisoire d’assertions dans le script va permettre d’anticiper sur les erreurs possibles de logique.
Le mécanisme d’assertion est là pour empêcher des erreurs qui ne devraient pas se produire, en arrêtant prématurément le programme. C’est un mode de programmation défensif, dans lequel on vérifie les préconditions.
Lorsque l’on execute la fonction inverse avec zero comme argument, le programme s’arrête et renvoie le message suivant dans le Traceback:
inverse(0)AssertionError:argumentnul
Mais l’interêt réside surtout dans l’utilisation d’assertion pour prévenir une possible erreur logique:
On souhaite maintenant obtenir le même comportement (arrêt pour une valeur sortant de l’ensemble de définition d’une fonction) pour la fonction de conversion de degré Celsius en degré Kelvin. En effet, il n’y aurait aucun sens de convertir une température inférieure à la température correspondant au zéro absolu. (exemple issu de univ.lille)
defen_kelvin(c):"""
conversion en kelvin d'une température donnée en Celsius
C.U. c doit être supérieure au zéro absolu.
"""assertc>-273.15,"valeur inferieure au zero absolu"return9*c/5+32
L’instruction raise permet au programmeur de déclencher une exception spécifique. Son utilisation diffère un peu de assert, car la condition qui déclenche l’arrêt du programme devra être ajoutée:
Notez que le type d’erreur exprimé après l’instruction raise est librement choisie par le programmeur, mais elle doit exister dans le langage Python. (IndexError, SyntaxError, ValueError, …)
Gestion des exceptions: try-except
Le mécanisme try-except va combiner des pré-conditions et post-conditions.
On pourra consulter les compléments sur la gestion des exceptions:
Le mécanisme des exceptions permet au programme de « rattraper » les erreurs, de détecter qu’une erreur s’est produite et d’agir en conséquence afin que le programme ne s’arrête pas.
Afin de rattraper l’erreur, on insère le code susceptible de produire une erreur entre les mots clés try et except.
Méthode :
try:# ... instructions à protégerexcept:# ... que faire en cas d'erreurelse:# ... que faire lorsque aucune erreur n'est apparuefinally:# ... ce que l’on réalise quel que soit le fonctionnement precedent
L’instruction try fonctionne comme ceci.
Premièrement, la clause try (instruction(s) placée(s) entre les mots-clés try et except) est exécutée.
Si aucune exception n’intervient, la clause except est sautée et l’exécution de l’instruction try est terminée.
Si une exception intervient pendant l’exécution de la clause “try”, le reste de cette clause est sauté. Si son type correspond à un nom d’exception indiqué après le mot-clé except, la clause “except” correspondante est exécutée, puis l’exécution continue après l’instruction try.
Exemple 1:
definverse(x):y=1.0/xreturnytry:a=inverse(2)print(a)b=inverse(0)# déclenche une exceptionprint(b)except:print("le programme a déclenché une erreur")# affiche : 0.5leprogrammeadéclenchéuneerreur
Testez le vous-même: créez une liste d’entiers pour x. Et essayez (try) de mettre dans une nouvelle liste les valeurs retournées par inverse, à moins (except) que la valeur de x soit nulle.
Exemple 2:
Si on veut convertir un caractère en entier, cela génère une erreur de type ValueError:
>>>int(input("Please enter a number: "))Pleaseenteranumber:qValueError:invalidliteralforint()withbase10:'q'
On peut utiliser un mecanisme d’exception pour rattraper cette erreur possible:
whileTrue:try:x=int(input("Please enter a number: "))breakexceptValueErrorastyp:print("Oops! That was no valid number. Try again...: {}".format(typ))print('=> vous avez entré le nombre {}'.format(x))
Executons ce script:
Please enter a number: d
Oops! That was no valid number. Try again...: invalid literal for int() with base 10: 'd'
Please enter a number: Z
Oops! That was no valid number. Try again...: invalid literal for int() with base 10: 'Z'
Please enter a number: 2
=> vous avez entré le nombre 2
Programmer des tests FONCTIONNELS
tests fonctionnels: ils verifient qu’un programme ou une partie du programme se comportent correctement, et se conforment à leur specification.
Fonctionnel: avec un Doctest
Le doctest est un module qui recherche dans le prototypage (docstring) de la fonction ce qui pourrait s’apparenter à des tests sur la fonction.
On écrit alors une simulation d’un essai directement dans le docstring, en écrivant de manière explicite les 3 chevrons. Ainsi que la valeur attendue pour des arguments choisis. (voir le paragraphe précédent)
Comme par exemple:
>>> a_rect(2,3)
6
Cette information sera placée dans le docstring de la fonction, et servira à anticiper des erreurs commises lors de la programmation.
Pour déclencher les tests sur la fonction, on ajoutera alors à la suite du script les lignes suivantes:
Fonctionnel: avec un module de test unitaires: unittest
Définition: Un test unitaire est un test réalisé sur une portion du programme, typiquement sur une fonction.
Le module unittest offre des outils de test de code, comme la classe TestCase. Le but est de vérifier que votre code génère des résultats corrects, conformes au attentes.
Les noms des classes de test se terminent généralement par TestCase (scenario de test). La classe créée pour le test, MyTest doit être une classe enfant de unittest.TestCase, d’où l’instruction class MyTest(unittest.TestCase):
Chaque test à créer est une méthode. Toute méthode dont le nom commence par test_ est exécutée lors du test. La méthode test_add appelle donc la fonction add avec les arguments 3 et 4, puis vérifie que son résultat est conforme, grâce à un test d’assertion assertEqual.
Or, ici, on fait le test d’assertion suivant: on vérifie si lorsque l’on appelle la fonction s.split avec l’argument 1, cela génère un TypeError, ce qui est VRAI. Donc le test REUSSI!
Par contre, avec self.assertRaises(TypeError,s.split,' '), cela echoue…
Fail:
Tests failed in MyTest.test_split
Ran 1 tests, passed: 0 failed: 1
Testez ces exemples
Ces exemples peuvent être testés dans l’éditeur en ligne Trinket.
Modifiez le programme deposé sur Trinket pour separer dans 2 fichiers: le fichier de test et le fichier contenant la fonction à tester.
Autres tests
En fait, unittest.TestCase propose plusieurs méthodes d’assertion que nous utiliserons dans nos tests unitaires.
Complexité
Complexité, notation de landau, algorithmes de recherche et de tri
algorithmes de tri
tris quadratiques, tri fusion, complexite
diviser pour regner
methode diviser pour regner, exponentiation rapide, tri fusion
rotation quart de tour
images matricielles, rotation, methode diviser pour regner
algorithmes avancés
algorithme d’optimisation, glouton, dynamique
algorithme de Boyer Moore
algorithme de Boyer Moore de recherche d’un motif dans une sequence
calculer sur un algorithme
calculabilite, decision, preuves
Paradigmes des langages Impératif Fonctionnel on ne trouve ni affectation (ou assignation), ni séquence (succession inconditionnelle de deux instructions).
Récursif Objet langages mathematiques
langages mathematique, chiffres, operateurs, logique
recursivité
cours recursivite
programmation orientée objet
cours POO, classe, instanciation, accesseur getter et mutateur setter
fichiers
gestion des fichiers par le systeme d’exploitation
systeme d’exploitation
processus, ordonnancement, interblocage
graphes et internet
Modéliser le réseau internet, graphes, équipement, adresses IP, tables de routage
protocoles de routage
routage statique et dynamique, ospf etat de liens, rip vecteur de distance
chiffrement symetrique
securisation des communications, chiffrement symetrique, code cesar, analyse frequentielle
chiffrement asymetrique
chiffrement asymetrique, RSA, HTTPS
TP table de routage
TP Filius simulation d’un reseau, table de routage
bases de donnees relationnelles
structuration des donnees, cles primaires et etrangeres, schema d’une relation
langage SQL
cours langage sql
TP prenoms sql
application du cours sql, base de donnees des prenoms
TP romans sql
TP avec SGBD sqlitebrowser, livres, bibliotheque
SQL - python
TP page web interactive avec base de donnees, python sqlite, module Flask
TP base de libreoffice
TP utilisant le SGBD BASE de libreoffice, films
Exercices classiques pour se préparer à l’epreuve. algos essentiels
bases en python, listes, dictionnaires, recherche, min, max
repondeur telephonique
generer un dictionnaire de contacts et mesurer les performances de recherche
Recherche Exoplanetes
ASTEP, exoplanetes, sequences
Courbes de transit
exploration des dossiers et fichier avec le module os, analyse courbe de transit, moyenne glissante
dataframes
calcul des caracteristique de l’exoplanete
projet Dominos
interface graphique TKinter, POO, dominos
Pygame Snake
interface IHM avec pygame, liste chainee
Jeu du Morpion
Projets utilisant les tableaux python version TNSI
arts numeriques
turtle, arts graphiques numeriques
ABR applications
arbre binaire de recherche, inventaire et rangement
GO: presentation Thèmes et articles Préparer l’entretien Le Grand Oral Découvrir l’épreuve du Grand Oral Présentation de l’épreuve et Foire aux Questions: http://quandjepasselebac.education.fr/faq-grand-oral/
La durée de l’epreuve est de 20 minutes, partagés en:
10 min d’exposé oral. 10 min d’entretien Construire sa question en rapport avec la spécialité NSI L’élève doit proposer 2 questions au jury, qui choisira celle qui sera presentée par le candidat. Ces questions portent obligatoirement sur les 2 spécialités de terminale, en combinaison. (une spécialité par question, ou 2 specialités représentées sur l’une des 2 questions, et une ou deux spé pour la 2e question).
algorithmes de recherche des nombres premiers: LienFeuille d’exercices en version pdf
Cout spatial et temporel
L’execution d’un algorithme nécessite l’utilisation des ressources de l’ordinateur:
complexité en temps : temps de calcul pour executer les operations. On supposera qu’il correspond au nombre d’opérations effectuées par le programme.
complexité spatiale : occupation de la mémoire pour contenir et manipuler le programme et ses données. Peut s’exprimer en nombre de mots mémoires.
Complexité temporelle
C’est une estimation du temps d’execution d’un programme, independamment de la machine.
En pratique, cela correspond au nombre d’opérations effectuées par le programme.
Pour evaluer la complexité temporelle, on peut mettre en evidence plusieurs opérations fondamentales. Le temps d’éxecution d’un algorithme resolvant ce genre de problème est toujours proportionnel au nombre de ces opérations :
Pour le tri, par exemple : ces opérations fondamentales sont le nombre de comparaisons entre 2 élements et le nombre de deplacements de ces élements.
Complexité spatiale
Il faut souvent définir une mesure sur les données qui réflète la quantité d’informations contenues. Exemple : nombre de chiffre des nombres, le nombre d’éléments manipulés, dimension d’une matrice, nombre de noeuds d’un graphe…
C’est la complexité spatiale.
Evaluer la complexité (temporelle)
Principe
Étant donnée que la durée d’exécution d’un algorithme peut varier entre différentes entrées, on considère généralement la complexité temporelle dans le cas le plus défavorable, qui correspond à la durée maximale.
Par exemple, avec l’algorithme de recherche séquentielle, ce temps correspondrait à trouver l’élément dans la liste comme s’il occupait la dernière position (voir plus loin).
La complexité d’un algorithme sera alors (sauf mention contraire) exprimée sous la forme : O(g(n)). Ce qui correspond à la complexité asymptotique, dans le pire des cas (sa borne supérieure).
En pratique, on ne comptera que les opérations estimées importantes : T(n). Les opérations qui ne changent pas selon les nuances du langage utilisées lors de la programmation (boucle while et boucle for…) mais qui changent selon le problème. Ce nombre d’opérations sera appelé T(n).
On en déduira alors la classe de complexité asymtotique g(n) (voir tableau plus loin). Puis la complexité dans le pire des cas O(g(n)).
Instructions élémentaires T(n)
T(n) est la somme des unités de mesure, comptée pour chaque instruction.
Une unité de mesure peut-être :
une addition
une soustraction
une multiplication, une division, Mod (%), Div
une opération arithmétique simple (sans appel de fonctions)
une comparaison, les opérations booléennes (et,ou,non)
une affectation
des opérations de lectures et écritures simples
Exemple:
Le programme multiplie devra écrire dans une liste la série de nombres correspondants à la table de multiplication de b. Pour les n premiers termes.
Exemple avec une boucle bornée
Supposons pour cet exemple que seules les opérations multiplier et additionner sont significatives. On compte le nombre de ces opérations pour les fonctions suivantes.
La première étape est d’identifier les séquences dans un algorithme. Si votre algorithme est composé des séquences :
I1
I2
I3
...
$$T(n) = T(I_1) + T(I_2) + T(I_3) + ...$$
il y a 3 séquences I1, I2, I3 :
# sequence I1L=[]
# sequence I2foriinrange(n):y=b*iL.append(y)
# sequence I3returnL
La séquence I1 contient une seule instruction élémentaires (affectation = ). I3 ne contient pas d’instruction significative. I2 est une séquence comprenant 3 operations :
opération * pour b * i
affectation =
affectation append
De ce fait :
$$T(n) = 1 + 3\times n$$
Boucle non bornée : variant de boucle
Le principe est le même pour une boucle non bornée (non conditionnelle), mais il est moins facile de déterminer le nombre d’itérations de la boucle. Pour ce faire, la méthode classique est d’étudier plus en détails le variant de boucle. On détermine :
La valeur initiale du variant de boucle ;
Sa valeur finale ;
De combien il diminue strictement à chaque étape.
On peut alors en déduire le nombre d’itérations de la boucle.
Exemple : Avec multiplie2, le variant de boucle, c’est i. Sa valeur passe de n - 1 à 0. La boucle est executée n fois. Et le nombre d’instructions significatives dans la boucle est de 2 :
La fonction semble réaliser plus d’opérations que la première implémentation, d’où la petite différence pour la valeur de T(n) avec les deux fonctions precedentes.
Ici, on peut évaluer T(n) = 2 + 5n
Cette différence ne vient que d’une différence des details d’implémentation du même algorithme, et ne doit pas être considérée pour le calcul de la complexité.
g(n): Limite asymptotique en n
Lorsque l’on étudie la complexité d’une fonction ou d’un algorithme, on s’intéressera souvent à son comportement pour de grandes taille du paramètre d’entrée n. Car si pour des données de petite dimension, la qualité de l’algorithme importe peu, pour de grandes tailles de données, la différence de performance peut être énorme. On dit que l’on observe le comportement asymtotique de T(n), c’est à dire pour n qui tend vers de grandes valeurs.
On aura besoin de définir plusieurs niveaux de description:
T(n), qui représente le nombre d’opérations significatives réalisées par cette fonction : par exemple $T(n) = 2\times n$.
g(n) est une approximation de T(n). Ici, $g(n) = n$
La complexité O(g(n)) détermine la classe de complexité de la fonction, dans le pire des cas. Dans le cas de nos 3 fonctions multiplie, ce sera à chaque fois O(n). La complexité est linéaire.
La petite différence d’implementation de ces 2 fonctions est visible en calculant T(n), mais pas en déterminant g(n) ni O(g(n)).
Règles pour estimer la complexité O(g(n))
Règles
Poser n = “la taille des paramètres”.
Enoncer les instructions que vous compterez comme significatives
définir des blocs d’instructions dans le script
Ne compter que les instructions essentielles, à partir d’une unité de mesure: noter la somme des instructions élémentaires T(n).
Pour chacune des boucles du programme, repérer le variant de boucle et calculer le nombre d’itérations : combien de fois on passe dans la boucle.
Si T(n) contient une somme de termes, conserver uniquement le plus divergent.
Prendre pour g(n) une fonction approchée de T(n). Ne pas considérer les multiplicateurs C : si T(n) = C.f(n), alors g(n) = f(n). Par exemple, si $T(n) = 3\times n$, prendre g(n) = n
Sauf précision contraire, la complexité demandée est la complexité au pire en temps.
Remarques :
C’est souvent le genre du problème qui va décider de ce qui constitue une instruction significative: Pour un algorithme de tri, ce sera : le nombre de comparaison de deux éléments, et le déplacement de deux éléments.
En faisant varier le degré de précision dans la mesure du nombre d’instruction élémentaires, on fait varier aussi le degré d’abstraction, c’est à dire l’independance par rapport à l’implementation de cet algorithme.
Principales classes de la complexité
Ces complexités sont classées par temps d’execution croissant de l’agorithme correspondant.
complexité
classe
Θ(1)
temps constant
Θ(log n)
logarithmique en base 2 : log2(n)
Θ(n)
linéaire
Θ(n*log n)
quasi linéaire
Θ($n^2$)
quadratique, polynômial
Θ($n^3$)
cubique, polynômial
Θ($2^n$)
exponentiel (problème très difficiles)
On peut observer l’evolution des courbes t(n) en fonction de n (nombre de données). t(n) sera le temps linéaire:
1 et log(n) : log(n) a une croissance faible
n*log(n) et n ont une croissance comparable
n**2
n**3
2**n
Les problèmes à résoudre ont le plus souvent un nombre n de données bien supérieur à 15, comme présenté sur le dernier graphique. Les effets de convergence sont donc encore plus marqués.
Approfondir la notion de complexité : voir annexe1
Supposons que le problème posé soit de trouver un nom X dans un annuaire téléphonique qui consiste en une liste triée alphabétiquement. On peut s’y prendre de plusieurs façons différentes. En voici deux :
Recherche linéaire : parcourir les pages dans l’ordre (alphabétique) jusqu’à trouver le nom X cherché. C’est l’algorithme de lecture exhaustif, aussi appelé algorithme de recherche linéaire.
Recherche dichotomique : ouvrir l’annuaire au milieu, si le nom qui s’y trouve est plus loin alphabétiquement que le nom cherché, regarder avant, sinon, regarder après. Refaire l’opération qui consiste à couper les demi-annuaires (puis les quarts d’annuaires, puis les huitièmes d’annuaires, etc.) jusqu’à trouver le nom cherché.
Algorithme de lecture exhaustif (recherche linéaire)
Cet algorithme pourrait fonctionner même si les éléments (mots, cartes, valeurs…) sont rangés dans le désordre : il s’agit de parcourir tous les mots, du premier au dernier, jusqu’à tomber sur le mot recherché dans cet liste ou annuaire.
Illustration avec un jeu de cartes non trié: Cherchons la dame de coeur dans la main d’un joueur.
main du joueur
On suppose que la seule manière de parcourir le jeu du joueur est de retourner les cartes une à une. On s’arrête si on trouve la carte. Ou bien si on arrive à la fin sans avoir trouvé la bonne carte.
La fonction suivante réalise une recherche linéaire de la valeur X sur une liste L de valeurs numériques. Pour la recherche d’une carte dans un jeu de cartes, ou d’un nom X dans un dictionnaire, il faudra adpater légèrement le script, mais la structure est la même.
defrecherche(X,L):"""
recherche une valeur dans une liste et renvoie l'indice si la valeur est trouvée, -1 sinon
Params :
-------------------
X : int, valeur à trouver
L : list, une liste de valeurs entieres, dans un ordre quelconque.
Sortie :
------
j : int, indice de la position de la valeur dans la liste
Principe :
--------
on parcourt la liste avec une boucle non bornée, tant que X n'est pas trouvé dans la liste
on augmente la valeur de j à chaque nouvelle itération
"""j=0n=len(L)whilej<nandX!=L[j]:j+=1ifj==n:return-1returnj
Pour evaluer la complexité de cette fonction, on suivra la méthode suivante:
evaluer la taille des paramètres n
Pour chacune de ces méthodes il existe un pire des cas et un meilleur des cas.
Dans le meilleur des cas, le nom X est trouvé dès l’ouverture de l’annuaire: il n’y aura alors qu’une seule étape.
Supposons que l’annuaire contienne N = 30 000 noms, si le mot recherché est le dernier du dictionnaire, le pire cas, cela demandera 30 000 étapes. La complexité est proportionnelle au nombre n. On la note O(n), ça veut dire que dans le pire des cas, le temps de calcul est de l’ordre de grandeur de n.
faire le détail des opérations réalisées et calculer T(n)
L’algorithme est constitué de 3 blocs d’instruction :
# bloc I1
j = 0
n = len(L)
# bloc I2whilej<nandX!=L[j]:j+=1
# bloc I3ifj==n:return-1returnj
Les éléments significatifs pour analyser le nombre d’opérations sont :
le nombre d’itérations
le nombre d’opérations par itération
I1 contient 2 instructions.
I3 contient 2 instructions (une comparaison et une instruction return)
Pour le bloc I2 : La variant de boucle, c’est n-j qui doit être >0 pour que la boucle continue.
Si la condition X!=L[j] n’est jamais realisée, cette boucle est alors executée n fois, avec j qui varie de 0 à n-1.
L’instruction j+=1 peut compter pour une instruction
Chacune des conditions d’arrêt j<n et X!=L[j] peuvent être considérées comme significatives. Il y aura alors 3 instructions par itération.
On aura, dans ce que l’on appelle le PIRE des cas (l’élément n’est pas trouvé): $T_2 (n) = 3\times n$
On fait alors la somme des 3 termes : $T(n) = T_1 (n) + T_2 (n) + T_3 (n)$
$$T(n) = 2 + 3\times n + 2$$
Calcul de la complexité
Complexité dans le meilleur et le pire des cas: Le nombre d’opérations T(n) se situe entre Min(n) et Max(n)
Min(n) = 7 : meilleur des cas (l’élément cherché occupe la premiere position dans la liste)
et Max(n) = n : pire des cas (l’élément cherché n’est pas dans la liste)
En notation de Landau, on écrit que la complexité (dans le pire des cas) est: O(n)
L’idée est de réduire l’intervale des abscisses de moitié à chaque itération, jusqu’à ce que l’encadrement [a,b] de la valeur x soit inférieur à l’intervale de confiance voulu (valeur ε) : jusqu’à ce que : $b-a < \epsilon$
On va adapter le raisonnement réalisé avec la recherche du zero de la manière suivante :
Soit une liste L d’objets triés dans l’ordre croissant (une liste de mots, ou de cartes à jouer…), et un objet X à trouver dans cette liste : On recherche la position (l’indice) de X dans la liste L en procédant par dichotomie si :
On part d’un intervale [a,b] sur les indices de la liste.
On calcule le milieu (ou du moins la valeur proche) m = (b-a) // 2
si X se trouve dans la partie inférieur, c’est à dire si X < L[m] : on prend l’intervale [a,m]
sinon on prend l’intervale [m,b]
A chaque itération, l’intervale est réduit de moitié. Le programme s’arrête lorsque l’intervale ne contient qu’un seul indice (a et b son égaux).
Illustration avec un jeu de cartes trié : rechercher la Dame de coeur
recherche dans un jeu de cartes triées
Le script python complet
defrechDico(L,X):gauche=0droite=len(L)trouve=Falsewhilegauche<=droiteandnottrouve:# On se place au milieu de la listemilieu=(gauche+droite)//2# il, s'agit d'une division entièreifL[milieu]==X:#print(élément, "trouvé à l'indice:", milieu , liste[milieu]) trouve=True# on arrête la boucleelifL[milieu]<X:gauche=milieu+1else:droite=milieu-1#print(élément, "non trouvé")ifnottrouve:return-1returnmilieu
Complexité
La dimension des données sera prise comme egale à len(L). Appelons cette valeur n.
Le variant de boucle, c’est $droite-gauche$, qui vaut au départ n, et 0 à la fin de la boucle, si la valeur n’a pas été trouvée (pire des cas).
Les instructions essentielles de la boucle, ce seront les comparaisons
L[milieu] == X
et L[milieu] > X
Pour simplifier le raisonnement, disons qu’il n’y a qu’une seule instruction essentielle par itération.
A la fin de la première itération, le variant de boucle vaut n/2.
On peut alors exprimer le nombre d’opérations T(n) pour cet algorithme comme égal à :
$$T(n) = 1 + T(n/2)$$
On aura, avec le même raisonnement,
$$T(n/2) = 1 + T(n/4)$$
Et ainsi de suite jusqu’à ce que n//2, et le variant de boucle, soient egaux à 0.
On a alors $T(n) = 1 + 1 + ...$ un nombre de fois égal au nombre de divisions par 2 de n, nécessaires pour amener n à 0. Cette valeur est egale à $log_2(n)$.
Le second algorithme demandera dans le pire des cas de séparer en deux l’annuaire, puis de séparer à nouveau cette sous-partie en deux, ainsi de suite jusqu’à n’avoir qu’un seul nom. Le nombre d’étapes nécessaire sera le nombre entier qui est immédiatement plus grand que $log_2 (N)$, qui vaut 15 lorsque N=30 000.
La complexité est alors O(log2(N))
Le tri par insertion
Principe
On recherche le plus petit élément et on le met à sa place (en l’échangeant avec le premier). On recherche le second plus petit et on le met à sa place, etc.
deftri_selection(L):n=len(L)foriinrange(0,n-1):#recherche le plus petit élément de i à la finmini=iforjinrange(i+1,n):ifL[j]<L[mini]:mini=j#échanger les cases i et minitmp=L[i]L[i]=L[mini]L[mini]=tmp
Description: boucle externe et boucle interne
Dans la boucle externe: On pose i comme position droite du tableau déjà trié. La valeur L[i] sera permutée avec la plus petite valeur trouvée dans la partie droite du tableau, celle non triée.
Dans la boucle interne. Le variant j représente l’index dans la partie droite, non triée du tableau. Le tableau non trié commençant au rang i+1, j va varier de i+1 à len(L). On recherche le rang de la plus petite valeur, rang que l’on appelle mini. La plus petite valeur est alors L[mini].
Permutations
Une fois identifié la valeur mini: On permute L[i] avec L[mini]. Pour permuter 2 valeurs, il faut utiliser une 3e variable, appelée tmp:
tmp=L[i]L[i]=L[mini]L[mini]=tmp
Complexité du tri par sélection
La boucle interne est executée n-1 fois, vu qu’elle est appelée à chaque itération de la boucle externe: for i in range(0, n - 1).
Dans la boucle interne, supposons que les opérations significatives sont celles de comparaison: if L[j] < L[mini]. On compte alors 1 seule opération à chaque itération de la boucle interne.
Pour la première itération de la boucle externe, i=0. Donc, pour la boucle interne, la boucle for s’écrit for j in range(1, n). Il y a alors n-1 itérations.
Pour la deuxième itération de la boucle externe, i=1. Pour la boucle interne, on a alors for j in range(2, n). Il y a alors n-2 itérations.
Le nombre d’itérations de la boucle interne vaut n-1. On a alors n-1 termes pour le calcul de T(n), dont les valeurs iront de n-1 à 1:
$$T(n) = (n-1) + (n-2) + ... + 1$$
Il s’agit d’une somme de n-1 termes d’une suite arithmétique, tels que $u_0 = 1$ et $u_{n-1} = n-1$
La complexité, exprimée en notation de Landau est donc $O(n^2)$. La classe de complexité est donc quadratique.
L'essentiel à retenir
Complexité temporelle
Definition
C’est une estimation du temps d’execution d’un programme, independamment de la machine, et des details d'implementation.
En pratique, cela correspond au nombre d’opérations effectuées par le programme. Ce nombre d’opérations dépendant de la taille n des données en entrée, on évalue d'abord une fonction T(n).
Ensuite, on fera une simplification de T(n) que l'on note g(n) g(n) peut être égal à 1, log(n), n, n.log(n), n2, ... 2n
Notation de Landau
Le plus souvent, il s’agira d’estimer la complexité dans le pire des cas, exprimée sous la forme : O(g(n)).
Pour l’exemple sur la fonction multiplie, la complexité est notée O(n) en notation de Landau.
Lorsqu’il est possible de déterminer une valeur exacte de la complexité, la notation devient Θ(g).
Règles pour estimer la complexité O(g(n))
Poser n = “la taille des paramètres”.
Ne compter que les instructions essentielles, à partir d'une unité de mesure: noter la somme T(n)
Pour chacune des boucles du programme, repérer le variant de boucle et calculer le nombre d’itérations : combien de fois on passe dans la boucle.
Si T(n) contient une somme de termes, conserver uniquement le plus divergent.
Prendre pour g(n) une fonction approchée de T(n). Ne pas considérer les multiplicateurs C : si T(n) = C.f(n), alors g(n) = f(n). Par exemple, si T(n) = 3*n, prendre g(n) = n.
Sauf précision contraire, la complexité demandée est la complexité au pire en temps.
Principales classes de complexité
Ces complexités sont classées par temps d’execution croissant de l’agorithme correspondant.
Déterminer la complexité des fonctions suivantes en terme de nombre d’additions et de soustractions. On donnera d’abord la valeur exacte T(n) puis l’ordre de grandeur O(n).
Dans un groupe de n individus , une star est quelqu’un que tout le monde connait mais qui ne connait personne. Pour trouver une star, s’il en existe une, vous ne pouvez poser aux individus de ce groupe que des questions du type : « connaissez-vous x ? ».
Combien de stars au maximum peut-il exister dans un groupe ?
Donner un algorithme trouvant une star s’il en existe une (ou déterminant qu’il n’en existe pas) et de coût linéaire (en prenant comme mesure de la complexité le nombre de questions posées).
Exercice 4 :
Le problème est de déterminer à partir de quel étage d’un immeuble sauter par une fenêtre est fatal. Vous êtes dans un immeuble à n étages (numérotés de 1 à n) et vous disposez de k étudiants. Il n’y a qu’une opération possible pour tester si la hauteur d’un étage est fatale : faire sauter un étudiant par la fenêtre. S’il survit, vous pouvez le réutiliser ensuite, sinon vous ne pouvez plus.
Vous devez proposer un algorithme pour trouver la hauteur à partir de laquelle un saut est fatal en faisant le minimum de sauts.
Donnée: on suppose k > n
Compléments sur le Calcul de T(n)
Pour calculer la complexité d’une boucle bornée. Soit (deb,fin) ∈ Z2, considérons une boucle de type for i in range(deb, fin):
Pour faire un calcul exact du nombre d’opération, il faut compter:
l’initialisation de la variable utilisée comme variant de boucle
l’incrémentation de cette variable
la comparaison avec la valeur d’arrêt
Parfois, le calcul de la complexité ne doit pas dépendre du type de boucle, et donc du type d’algorithme. Ces opérations ne sont alors pas comptées.
Instructions conditionnelles
conditionnel simple
Si Condition Alors :
I ;
Dans le cas défavorable, où l’expression conditionnelle revoie True, le bloc d’instruction I est exécuté. On a alors :
$$T (n) = Tcondition (n) + T_I (n)$$
T(n) représente le nombre total d’instructions
Tcondition(n) représente le nombre d’instructions nécessaire pour tester la condition (qui peut-être 1 s’il s’agit par exemple d’une simple comparaison entre deux expressions arithmétiques).
En pratique, la recherche de la complexité revient à déterminer cette fonction (ou cette suite) g. On note la complexité O(g). On ignore l’eventuel coefficient multiplicateur c et on ne conserve que le terme le plus divergent dans le cas où g contienne plusieurs termes. T(n) = O(g(n)).
Pour l’exemple précédent, la complexité est notée O(n) en notation de Landau.
Notation Θ : Lorsqu’il est possible de déterminer une valeur exacte de la complexité, la notation devient Θ(g).
Complexité en moyenne Θ(g(n)):
$$Moy_A(n) = \sum_{d \in D_n} p(d).coût_A(d)$$
où p(d) est la probabilité que l’on ait la donnée d en entrée de l’algorithme.
et coût_A(d) représente la complexité en temps de l’algorithme A sur la donnée d.
Les activités de tri sont très fréquents en informatique. Dans un projet informatique, on préfère qu’un programme passer du temps à trier les données plutôt qu’à les rechercher.
On presente dans ce chapitre TROIS algorithmes de tri. Mais il en existe de très nombreux, dont l’efficacité diffère grandement. Voici un aperçu de la durée comparée de quelques algorithmes de tri, selon la nature de la liste à trier:
comparatif de performance de quelques algorithmes de tri
Nombre d’éléments « n »
Nombre d’opérations pour un tri en « O(n²) »
Durée pour un tri en « O(n²) »
10
100
100 ns
100
10 000
10 us
1 000
1 000 000
1 ms
10 000
100 000 000
100 ms
100 000
10 000 000 000
10 s
1 000 000
1 000 000 000 000
16 min 40 s
10 000 000
100 000 000 000 000
27 heures
100 000 000
10 000 000 000 000 000
115 jours
1 000 000 000
1 000 000 000 000 000 000
31 ans
8 000 000 000 (population mondiale)
64 000 000 000 000 000 000
1984 ans
Pour un algorithme de complexité O(n.log(n)), la durée de tri d’un ensemble de 8 000 000 000 valeurs prendrait 4 min!
Pour cet algorithme, trier, c’est déplacer chaque élément, en suivant un ordre de la gauche vers la droite, et l’insérer dans la partie déjà triée (à sa gauche), à sa place. C’est un peu la manière avec laquelle on range les cartes à jouer au debut d’une partie:
main d'une partie de cartes
Hypothèse : l’élément non rangé est le j. Tous les autres éléments sont rangés jusqu’à j.
Il faut d’abord conserver sa valeur à l’aide d’une variable temp
On décale tous les éléments i, depuis le rang j jusqu’à l’élément dont la valeur est inférieure à celle de j (et donc de temp), en redescendant.
animation sur le tri par insertion
Sur l’animation: on devine le script de la boucle interne:
Dans la partie non triée, selectionner la premiere carte. La reserver en laissant la place libre
faire glisser les cartes de la partie gauche (triée) vers la droite pour laiser la place libre à la carte à insérer (correspond à un copier-coller des cartes i-1 => i)
Montrons qu’à la fin d’un tour de boucle, les valeurs de la liste sont triées jusqu’au rang j inclus:
au début, j vaut 0. Il ne se passe rien.
puis j vaut 1. temp vaut L[1]. Dans la boucle secondaire (while), à la ligne 5, si L[0] > temp, alors L[1] = L[0] puis L[0] = temp. La liste est alors triée jusqu’à j = 1 inclus.
supposons qu’à la fin du tour j-1, les valeurs sont triées jusqu’à j-1 inclus. Il faut alors montrer que, lors du tour j, la valeur temp (qui vaut L[j]) sera insérée au bon endroit.
Pour aider le raisonnement, on utlisera le tableau exemple suivant:
liste triée jusqu'au rang j = 3
Cas n°1: Soit L[j] >= L[0]:
Après la ligne 4, on entre dans la boucle while. A la fin de cette boucle, avant la ligne 8, on a la configuration milieu pour la liste.
Alors la boucle n’est plus executée car L[i-1] > temp vaut False, donc, ligne 9: L[i] = temp. La liste est alors dans la configuration fin de boucle sur l’image suivante.
liste triée jusqu'au rang j = 4 inclus
Cas 2: L[j] < L[0]: prendre l’élement au rang j = 5 de la liste précédente.
On verifie que while quitte pour i = 0 et que la clé temp est bien insérée dans la case 0. La liste est bien triée jusqu’à j = 5 inclus.
Conclusion: Lorsque la boucle for execute son dernier tour, j designe la dernière case, et on a bien montré que la liste sera bien triée jusqu’à cette case. Donc la liste est entièrement triée.
Complexité
Calcul du nombre d’opération
Supposons que la taille de la liste est n.
Les opérations significatives sont:
l’affectation
la comparaison
l’une des opérations arithmetiques: +, -, *, /
La boucle forest executée n fois.
Dans le pire des cas, où la liste classerait les éléments dans l’ordre décroissant, T(n) sera alors:
$$T_1(n) = n \times 2~(lignes~3~et~4)+ n~(ligne~8)$$
Dans cette variante du tri par selection, la liste est triée depuis le plus grand élément jusqu’au plus petit.
On modifie pour cela la fonction select: on remplace les instructions ndiceDuMin=debut et T[k]< T[indiceDuMin] afin de rechercher la valeur max et non celle min.
On peut compter le nombre de déplacements / affectations réalisés pour trier les valeurs de la liste, en fonction de la valeur i. Pour simplifier, on compte N = le nombre d’opérations d’affectations dans la boucle interne.
Pour l’exemple ci-dessus, ce nombre T(8) = 2 + 3 +’ 4 + 5 + 6 + 7 = 27
De manière plus générale: $T(n) = \tfrac{n \times (n-1)}{2}$, ce qui fait une complexité $O(n^2)$
Le tri fusion
Principe
Le tri pas fusion procède en 2 étapes distinctes. Il s’agit d’un algorithme de type récursif. Au cours de la descente, la liste de valeurs non triées est divisée en 2 parties égales (ou presque) à chaque appel recursif. Puis, lors de la remontée, ces listes, triées sont interclassées, comme vu sur l’animation suivante:
animation sur l'interclassement de 2 listes triées
C’est donc sur la remontée que l’on range les éléments par valeur croissante.
Sur l’animation: on devine le script de la fonction d’interclassement:
comparer les valeurs des bords gauche de chaque sous liste triée
ajouter le plus petit élément des 2 sous listes dans une troisieme liste
déplacer le bord gauche de la sous liste dont on a selectionné l’élément
L’algorithme est naturellement décrit de façon récursive.
Si le tableau n’a qu’un élément, il est déjà trié.
Sinon, séparer le tableau en deux parties à peu près égales.
Trier récursivement le sous-tableau de gauche avec ce même algorithme du tri
Trier récursivement le sous-tableau de droite avec ce même algorithme du tri
Fusionner les deux tableaux triés en un seul tableau trié.
Et la page sur les rappels: python avancé > algorithmes essentiels > algos de tri
Diviser pour regner
C’est une technique informatique qui consiste à :
Diviser : découper un problème initial en sous-problèmes de tailles équivalentes;
Régner : résoudre les sous-problèmes (récursivement ou directement s’ils sont assez petits) ;
Combiner : calculer une solution au problème initial à partir des solutions des sous-problèmes.
Cette méthode, lorsqu’elle s’applique, fournit un algorithme de complexité plus réduite, et donc plus efficace.
Definition : Un problème est de type diviser pour regner si sa resolution se ramène à celle de un ou plusieurs problèmes indépendants dont la taille des entrées passe de n à n/2, ou une fraction de n. Ou bien, si la division en plusieurs problèmes permet de réduire la durée necessaire pour sa resolution.
Exemple introductif : téléphone en chaîne
Les 15 joueuses d’une équipe de volleyball ont la liste des joueuses de l’équipe avec leur numéro de téléphone. La capitaine reçoit l’information que le prochain match a été déplacé. Il faut prévenir toutes les autres joueuses.
Solution 1 : la capitaine se charge d’appeler toutes les autres joueuses. Et si elle passe 5 minutes au téléphone avec chacune d’entre-elles…
Question à propos de la solution 1: En combien de temps (noté t1) l’ensemble de l’équipe est informé? En déduire la complexité de cette solution en fonction de n (taille de l’équipe)
Solution 2 : Une solution plus efficace et plus confortable pour la capitaine est qu’elle divise la liste de joueuses en deux moitiés. Elle appelle alors la première joueuse de chacune des deux listes obtenues. Elle leur donne l’information de report de match et leur demande à leur tour de faire la même chose : diviser en deux la demi-liste à laquelle elles appartiennent, appeler la première joueuse de chacune des parties et ainsi de suite … jusqu’à ce qu’il n’y ait plus personne à prévenir.
Représentons l’arbre des appels pour la liste de 15 joueuses numérotées de 1 à 15.
arbre des appels
Question à propos de la solution 2:Si on suppose qu’un appel téléphonique dure 5 min. En combien de temps (noté t2) l’ensemble de l’équipe est informé ? En déduire la complexité de cette solution en fonction de n (taille de l’équipe)
Conclusion: La solution 2 illustre bien la méthode Diviser pour regner puisqu’à chaque nouvel appel telephonique, le nombre de joueuses contactées avec le même message va doubler. La durée necessaire pour la resolution du problème initial (téléphoner à toutes les joueuses) est alors réduite de manière significative.
Exponentiation
L’exponentiation consiste à trouver une méthode pour calculer x à la puissance n, SANS utiliser l’opérateur puissance. L’idée est de se rappocher de l’algorithme utilisé par le processeur d’un ordinateur, qui n’utilise que les 3 opérateurs de base pour effectuer les calculs (+,-,*).
Programme itératif $x^n$
defexp1(n,x):"""
programme qui donne x^n en sortie
n : entier
x : reel
exp1 : reel
"""acc=1foriinrange(n):acc*=xreturnacc
Complexité
La boucle for est exécutée n fois. Il y a, à chaque itération, une opération arithmétique qui est réalisée (multiplication par x), et une affectation (le résultat est affecté à acc).
Il y a donc au total :
2n + 1 opérations.
La complexité est O(n).
Programme récursif $x^n$
defexp2(n,x):"""
n : entier
x : reel
exp2 : reel
"""ifn==0:return1else:returnexp2(n-1,x)*x
On pourrait montrer que la complexité est aussi O(n).
Exponentiation rapide $x^n$
application de la méthode diviser pour regner
Comme de nombreux algorithmes utilisant cette méthode, celui-ci fait des appels recursifs. Mais à la différence du précédent, l’appel recursif se fait avec un paramètre que l’on divise par 2 (le paramètre n). C’est ce qui fait que le nombre d’appels récursifs est plus réduit.
On retrouve l’étape 3 évoquée en introduction (la combinaison des sous problèmes) lorsque l’on réalise l’opération : return y*y ou bien return x*y*y.
defexp3(n,x):"""
programme plus efficace que le precedent car
le nombre d'operations est log2(n)
"""ifn==0:return1else:y=exp3(n//2,x)# on prend la valeur inferieure de n/2ifn%2==0:returny*yelse:returnx*y*y
Complexité
Prenons pour exemple n = 8 :
Dans la phase de descente:
exp3(8,x) appelle exp3(4,x) appelle exp3(2,x) qui appelle exp3(1,x) puis exp3(0,x).
Dans la phase de remontée: Une seule opération est réalisée à chaque appel recursif : y*y
C'est comme si l'on dupliquait le résultat de chaque multiplication (voir représentation en arbre plus bas)
exp3(0,x) retourne 1
exp3(1,x) retourne x * 1 * 1
exp3(2,x) retourne x * x
exp3(4,x) retourne x2 * x2
exp3(8,x) retourne x4 * x4
Le nombre d'opérations est le nombre de divisions par 2 qu'il faut faire pour reduire n à 0. Ce nombre est justement egal à : $$log_2(n)$$
représentation en arbre
L’exponentiation rapide peut être utilisée pour des “multiplications” plus compliquées, comme la multiplication de matrices, la composition de fonctions,... Dans ces cas, il ne faut pas oublier de compter le coût de la multiplication dans les calculs, qui n’est pas toujours constant.
Le Tri Fusion
Principe
Le tri fusion est un autre algorithme de tri. Celui-ci présente l’avantage d’utiliser la méthode Diviser pour Regner.
Les étapes 1 et 2 de la méthode Diviser pour Regner consistent à diviser la liste en 2 sous-listes, de manière recursive, jusqu’à obtenir des listes de 1 élément.
Le tri fusion est réalisé par la fonction fusion suivante:
La fonction fusion ressemble à celle du parcours récursif d’un arbre dans lequel, pour un noeud contenant une liste L:
le fils gauche est la sous-liste de gauche (la première moitié de L)
le fils droit est la sous-liste de droite (la deuxième moitié de L)
Le traitement se faisant APRES les 2 appels recursifs (gauche puis droite), le parcours s’apparente à celui appelé POSTFIXE.
parcours de l'arbre pour le tri fusion
Etude du tri fusion sur la liste L = [1,10,8,4,3,6]
Question 1:Compléter la séquence avec l’ordre des branches parcourues et les sous-listes à chaque noeud, jusqu’à ce que tout le sous-arbre gauche soit “divisée”.
La remontée dans la pile d’appels commence lorsque l’on arrive à une sous-liste d’un seul élément pour droite.
La fonction interclassement prend deux listes en paramètres, L1 et L2, et retourne une seule liste avec les éléments de L1 et L2, mais classés.
Question 2:Décrire les étapes jusqu’à ce que la liste L soit triée.
La complexité de la fonction interclassement est O(n), où n est égal à la taille de chaque sous-liste.
Question 3:Expliquer pourquoi, lors de la fusion, la complexité au rang n est donnée par la formule de recurence:
$$T(n) = T(\tfrac{n}{2}) + n$$
Question 4: En déduire la complexité du tri fusion.
Complexité du tri fusion
Le tri fusion est un tri qui est optimal du point de vue de la complexité temporelle: il est de l’ordre O(N*log(N)). On ne peut pas trouver un algorithme plus efficace en temps.
Analyse simplifée: A chaque étape de la remontée, lors de l’interclassement:
si l’on compte le nombre d’affectations: Il y a n affectations (n éléments partagés en 2 sous listes, à placer dans une nouvelle liste). Le nombre d’étapes est egal à $log_2(n)$. Ce qui fait un nombre d’opérations proportionnel à $n \times log_2(n)$.
Pour le nombre de comparaisons: Ce nombre est inférieur, à chaque étape, au nombre n d’éléments de la liste à trier. Le nombre de comparaisons est donc $< n \times log_2(n)$
On peut donc considérer que le tri fusion a une complexité asymptotique $n \times log_2(n)$
Remarque: l’inconvenient majeur de cet algorithme est qu’il demande beaucoup de ressources spatiales, du fait de la construction de nombreuses sous-listes pour réaliser le tri. Ce n’est pas un tri en place, comme on a pu le voir avec les algorithmes essentiels vus en classe de 1ere NSI.
Rappels de SNT: Une image numérique est constituée de pixels colorés (ou noirs et blanc). Le fichier comportant l’image numérique contient alors une succession de valeurs qui codent la couleur de chaque pixels: lire le cours de SNT, paragraphe
codage de l'image
Librairie PIL
Pour manipuler les images, nous pouvons utiliser le module PIL de Python. Celui-ci permet de traiter les pixels d’une image, un par un. Souvent, il faudra parcourir l’image pixel par pixel, sur toute la largeur et toute la hauteur. Cela est possible avec deux boucles imbriquées, à condition de connaitre ses dimensions largeur, hauteur:
fromPILimportImageimageSource=Image.open("crabePortrait.bmp")largeur,hauteur=imageSource.sizeforyinrange(hauteur):# y varie de 0 à hauteur - 1forxinrange(largeur):# x varie de 0 à largeur - 1# traitement pixel (x,y)
Les boucles for vont effectuer un parcours:
sur y (position en hauteur qui varie de 0 à hauteur-1)
sur x (position en largeur qui varie de 0 à largeur-1)
Le pixel (0,0) est en haut sur le coin gauche.
imageSource est une instance de la classe Image et possède une methode getpixel((x,y)) qui renvoie la valeur du pixel pour l’argument (x,y). S’utilise de la manière suivante:
Nous allons travailler sur l’image suivante: crabePortrait.bmp.
image de dimension 247 * 330 en format bitmap, RGB 3 octets
Défi n°1: explorer la structure de données
A vous de jouer: ouvrir le fichier rotation_crabe.py, analyser le script, puis, à l’aide de la fonction copie_image, faire une copie de l’image crabe_portrait.bmp
Vérifier le contenu des données pour quelques uns des points de l’image: afficher la valeur de p si x < largeur//10 et y < hauteur //10
Laquelle des structures de données représente le mieux le format des données:
[124,90,120]
(124,90,120)
#7C5A78?
Rotation d’une image: permutation de pixels
Défi n°2: Coordonnées pour une rotation droite
principe de la rotation horaire d'un quart de tour
Répondre aux Questions:
Quelles sont les coordonnées des points A et B avant transformation?
Quelles sont les nouvelles positions des points A’ et B’ après transformation: Pour un pixel situé initialement en (x,y), quelles sont ses coodonnées (x’,y’) après transformation?
Défi n°3: Rotation droite d’une image
En vous inspirant de la fonction copie_image, écrire une fonction rotation_droite qui réalise la rotation d’un quart de tour dans le sens horaire, comme sur l’image ci-dessus.
Permuter les zones d’une image
On cherche maintenant à effectuer cette transformation, SANS utiliser de nouvelle image planPixels comme précédemment.
On utilisera l’image suivante (carrée) pour cette méthode: woody.jpg
image woody.jpg
Le fichier de travail sera rotation_woody.py
Défi n°4: permutation de blocs
la fonction echange_quadrant permet d’echanger les pixels de 2 zones carrées de même dimensions.
exemple: echange des blocs A et B
Les zones échangées seront les 4 parties marquées A, B, C et D sur l’image ci-dessous.
image d'origine
Pour effectuer une rotation droite dans l’image, on va effectuer 3 permutations SUCCESSIVES sur les zones ABCD de l’image:
trois permutations réalisées sur les subdivisions de l'image
Pour échanger les zones A et B d’une image, et visualiser le résultat, utiliser la fonction permutation_blocs_A_B.
Ecrire les fonctions permutation_blocs_B_D et permutation_blocs_C_D. Appliquer les transformations pour obtenir une rotation droite des blocs de l’image woody.jpg.
Rotation par la méthode Diviser pour Régner
La fonction rotate permet de faire tourner l’image d’un quart de tour par une méthode de type diviser pour régner:
Tourner l’image d’un quart de tour, c’est permuter les 4 parties d’une image dont on a permuté l’interieur de ses 4 parties…
Une fois la partie divisée executée (appels recursifs), lorsque les subdivisions de l’image sont constituées d’un seul pixel, les pixels sont déplacés (règne) à l’aide de 3 permutations successives, selon le schéma suivant:
trois permutations réalisées sur les subdivisions de l'image
Il sont alors recombinés pour reformer l’image, tout en suivant les mêmes permutations, mais avec des blocs de pixels plus gros (fusion).
Le but est d’obtenir l’image suivante, à l’aide de la fonction quart_tour:
image finale
Défi n°5: rotation d’une image par la méthode Diviser pour régner
Compléter la fonction rotate pour obtenir une image à l’endroit de woody.
Expliquer pourquoi cette méthode s’apparente à la famille Diviser pour régner. (On pourra s’aider des schémas ci-dessous, et les remettre dans l’ordre pour repondre).
image a
image b
image c
image d
efficacité de la méthode
Evaluons l’efficacité de cet algorithme
Est-il plus rapide ou plus lent que votre premier algorithme?
Le nombre d’opérations significatives suit une loi de recurence: $T(n) = 4 \times T(\tfrac{n}{2}) + C \times n^2$ Cela confirme t-il votre reponse à la question pécédente?
On rappelle que l’intérêt de la méthode est surtout de ne PAS utiliser de nouvelle image planPixels comme précédemment. Il s’agit d’une transformation en place.
Liens et aides
En cas de difficulté, consulter la page et les videos du site: monlyceenumerique.fr, aller à la partie sur la rotation des images.
un exemple d’algorithme avec recherche locale. Pour la résolution d’un problème de TSP (Traveling salesman problem)
Les classes de problèmes de decision, P, NP, NP-complet
Programmation dynamique
Principe de la méthode
La programmation dynamique permet de résoudre plus efficacement des problèmes d’optimisation.
La programmation dynamique consiste à résoudre un problème en le décomposant en sous-problèmes, puis à résoudre les sous-problèmes, des plus petits aux plus grands en stockant les résultats intermédiaires, et en suivant une règle d’optimalité. La solution donnée par un algorithme glouton est optimale, mais n’est pas forcement la solution la plus optimale au problème.
Cela diffère des algorithmes de type diviser pour régner par le fait que les sous-problèmes considérés ne sont pas nécessairement indépendants. Pour les algorithmes de type diviser pour régner, on partitionne le problème en sous problèmes indépendants, qui seront résolus recursivement. Puis on combine leurs solutions pour résoudre le problème initial. Mais cela peut revenir à résoudre plusieurs fois le même sous-problème, et peut être parfois inefficace.
Pour la méthode de programmation dynamique, on va se rappeler des sous-problèmes résolus (de leurs solutions), et eviter de les re-calculer.
Cette méthode a été introduite au début des années 1950 par Richard Bellman.
Comment s’y prendre pour mémoriser les solutions?
La méthode demande alors de mémoriser ce résultat intermédiaire dans un dictionnaire ou un tableau afin de le réutiliser au besoin. Sans avoir besoin de les recalculer. La complexité spatiale augmente, mais celle temporelle diminue.
Cette méthode s’appelle : la mémoïzation.
Elle va permettre d’eviter la répétition des calculs que l’on voit dans l’exemple suivant, le triangle de Pascal. Sans cette reduction, la compléxité de l’algorithme est exponentielle (voir l’arbre des calculs, présenté plus bas).
Ce problème de répétitions a été vu avec l’exemple du calcul des termes de la suite de Fibonacci.
Limites de la méthode diviser pour regner : le triangle de Pascal
Principe
En mathématiques, le triangle de Pascal est une présentation des coefficients binomiaux dans un triangle. Il fut nommé ainsi en l’honneur du mathématicien français Blaise Pascal. Il est connu sous l’appellation « triangle de Pascal » en Occident, bien qu’il fût étudié par d’autres mathématiciens, parfois plusieurs siècles avant lui.
premières lignes du triangle de Pascal
Cette figure permet de calculer les coefficients binomiaux d’un polynôme (x+y) à la puissance n:
Les algorithmes de type diviser pour regner sont souvent exprimés de manière recursive.
defpascal_recur(n,p):# calcul d'un coefficient par recursivitéifp==0:return1ifp>n:return0else:returnpascal_recur(n-1,p)+pascal_recur(n-1,p-1)defpascal(n):T=[[0]*(n+1)forpinrange(n+1)]forninrange(n+1):forkinrange(n+1):T[n][k]=pascal_recur(n,k)returnT
On remarque que l’on calcule souvent les mêmes coefficients binomiaux :
arbre de calcul des coefficients pour n=4 p=2
On voit que certains termes, comme celui (n=2, p=1) est calculé plusieurs fois. Dans les branches (n=3, p=1) et (n=3, p=2). Cela est du au fait que les 2 branches de l’arbre sont indépendantes.
La mémoïzation consistera alors à stocker dans un tableau les solutions pour les sous-problèmes afin de ne pas les recalculer…
Algorithme avec mémoïzation
Chaque valeur du triangle n’est calculée qu’une seule fois.
L’algorithme non recursif, avec mémoïzation est plus efficace.
Problèmes de décision et algorithmes gloutons
Un algorithme glouton est un algorithme qui suit le principe de réaliser, étape par étape, un choix optimum local, afin d’obtenir un résultat optimum global.
Le problème du rendu de monnaie
Le problème du rendu de monnaie est un problème d’algorithmique. Il s’énonce de la façon suivante : étant donné un système de monnaie (pièces et billets), comment rendre une somme donnée de façon optimale, c’est-à-dire avec le nombre minimal de pièces et billets ?
Par exemple, la meilleure façon de rendre 7 euros est de rendre un billet de cinq et une pièce de deux, même si d’autres façons existent (rendre 7 pièces de un euro, par exemple).
Sur l’animation, l’algorithme traite TOUTES les combinaisons de rendu de monnaie. L’arbre des appels recursifs montre que la complexité de cette méthode croit exponentiellement avec la taille des paramètres d’entrée.
Contrairement aux problèmes étudiés précédement (tri d’un tableau, calcul de xn…), où il y avait toujours une unique solution, dans les problèmes d’optimisation, il peut y avoir des solutions valides (satisfaisant les contraintes) non optimales, une ou plusieurs solutions (valides), optimales (minimisant/maximisant une certaine mesure), voire pas du tout de solution valide.
Si la taille du ou des paramètres en entrée est importante, il n’y a pas d’algorithme déterministe efficace. (on ne peut pas trouver LA solution au problème en parcourant toutes les solutions possibles car la complexité est trop grande). Voir paragraphe suivant sur la recherche exhaustive.
On utilise alors d’autres stratégies, qui donneront parfois une solution, parfois une solution optimale. C’est ce que l’on réalise avec l’utilisation d’un algorithme glouton.
Le problème du rendu de monnaie est NP-difficile relativement au nombre de pièce et billet du système monétaire considéré. (voir annexe).
Algorithme exhaustif
Une première méthode, SANS stratégie, pourrait être d’envisager TOUTES les combinaisons. On pourrait alors imaginer que l’on commence par rendre la monnaie avec une des pieces de la caisse (pas forcément la plus haute), puis on choisit une autre piece possible (egale ou moins haute), … Jusqu’à ce que la somme à rendre soit nulle. On envisage ainsi toutes les combinaisons possibles, ce qui, avec une valeur élevée de la somme à rendre, et un grand nombre de pieces dans la caisse, va donner un très grand nombre de combinaisons. On selectionne enfin la meilleure des solutions (celle optimale).
Par exemple, pour rendre 7 euros, voici toutes les combinaisons possibles (la solution optimale étant la première):
5 + 2
5 + 1 + 1
2 + 2 + 2 + 1
2 + 2 + 1 + 1 + 1
2 + 1 + 1 + 1 + 1 + 1
1 + 1 + 1 + 1 + 1 + 1 + 1
On peut représenter cette recherche de solutions à l’aide d’un arbre: La racine est la somme à rendre. On descend dans l’arbre en faisant des choix, ce qui diminue la somme. Lorsque l’on arrive sur une feuille avec 0, c’est que l’on a trouvé une solution. La solution otimale est donnée ici en rendant 4 pieces de 7 (trajectoire presque verticale de 28 à 0):
wikipedia - Problème_du_rendu_de_monnaie
Représenter, comme sur l’image ci-dessus, une partie de l’arbre des combinaisons pour rendre un montant égal à 15, en choisissant une à une chaque piece de la caisse [1, 7, 9]. Quelle est la trajectoire dans cet arbre selon la méthode gloutonne? Quel est le choix optimal?
Un programme python exprimerait le rendu sous forme de liste:
Le problème est traité de cette manière en 1ere NSI:
Une caisse contient un nombre suffisant de pieces pour rendre la monnaie. Cette caisse est représentée par une liste triée en ordre croissant, et sera parcourue de la piece de valeur la plus élevée vers la moins élevée.
Supposons que l’on dispose d’une fonction recursive, qui pour chaque piece de la caisse fait le choix suivant:
soit la piece est inférieure à la monnaie à rendre: alors on soustrait la piece à la somme à rendre et on appelle la fonction de manière récursive avec cette même caisse, et la nouvelle somme à rendre.
soit la piece est supérieure à la somme à rendre. on retire la piece de la caisse. Et on appelle de manière récursive la fonction avec la nouvelle caisse, et la même somme.
La condition de base sera: la liste de pieces est vide.
On utilisera une liste rendu pour placer les pieces rendues.
Que renvoie la fonction pour rendre 53 pences avec le système imperial où pieces = [240,60,30,24,12,6,3,1] ?
Le rendu est-il optimal avec cette méthode? Ou bien existe t-il une autre façon de rendre la monnaie, avec moins de pieces?
Conclusion: Suivant le système de pièces, l’algorithme glouton est optimal ou pas. Dans le système de pièces européen (en centimes : 1, 2, 5, 10, 20, 50, 100, 200), où l’algorithme glouton donne la somme suivante pour 37 : 20+10+5+2, on peut montrer que l’algorithme glouton donne toujours une solution optimale. wikipedia
Algorithme glouton vs programmation dynamique
Un algorithme glouton fait un choix local immédiat et irrévocable à chaque étape, sans revenir en arrière. Pour le rendu de monnaie, il prendrait systématiquement la plus grande pièce possible. C’est simple et rapide, mais pas toujours optimal.
Exemple : rendre 15 avec {1, 7, 9} → le glouton prend 9, puis 6 × 1 = 7 pièces.
La programmation dynamique construit au contraire un tableau de solutions optimales pour tous les sous-problèmes, en s’appuyant à chaque étape sur les résultats déjà calculés. Elle garantit l’optimum.
Algorithme de programmation dynamique — rendu de monnaie
On cherche à rendre un montant x avec un minimum de pièces, choisies parmi n valeurs possibles.
Approche ascendante : on construit une table de solutions optimales pour tous les montants de 0 à x. On commence par les petits montants, puis on monte progressivement. Chaque montant est rendu de manière optimale en s’appuyant sur les résultats déjà calculés.
Principe : pour rendre le montant w, il faut au moins une pièce, à choisir parmi les n pièces disponibles. Une fois cette pièce choisie de valeur p, le montant restant w - p est strictement inférieur à w — on sait donc déjà le rendre de façon optimale (c’est déjà dans le tableau). Il suffit d’essayer les n possibilités et de retenir celle qui minimise le nombre total de pièces :
La réponse se lit dans la dernière case : dp[3][15] = 3 pièces (7 + 7 + 1).
Complexité
Comment cet algorithme parvient-il à reduire le nombre de combinaisons pour rendre la monnaie?
Le tableau comporte n × W cases (ici 3 × 15 = 45), chacune calculée en temps constant. La complexité est donc O(n · W) — à comparer avec la méthode exhaustive en O(2ⁿ) :
n
W
O(n · W)
O(2ⁿ)
10
100
1 000
1 024
30
500
15 000
≈ 10⁹
100
500
50 000
≈ 10³⁰
Pour des instances réalistes, la programmation dynamique est des milliards de fois plus rapide que la recherche exhaustive.
Remarques:
La subtilité importante : O(n·W) ressemble à du polynomial, mais W peut être très grand. Si les poids sont exprimés en grammes et que le sac fait 100 kg, W = 100 000. C’est pour ça que le sac à dos reste un problème dit NP-complet dans le cas général, c’est-à-dire difficile à résoudre. Cependant pour certains systèmes de monnaie dits canoniques, l’algorithme glouton est optimal.
Regarder aussi: le probleme de l’allocation des ressources pour un systeme d’exploitation: l’algorithme du banquier
Le problème du sac à dos
Un problème très similaire est celui du sac-à-dos. Supposons que vous découvriez la caverne d’Ali Baba (et des 40 voleurs), il y a une infinité d’objets de valeur v1, v2, · · · , vn mais chaque objet de valeur vi a un poids de pi. Comment remplir votre sac-à-dos avec le contenu qui rapportera le plus, sachant que votre sac ne supporte qu’un poids W?
Déterminer le choix idéal pour un sac à dos de capacité 32kg, avec les objets suivants, proposés en nombre infini: `[{“valeur”: 7, “poids”:17},{“valeur”: 4, “poids”:11},{“valeur”: 3.1, “poids”:9},{“valeur”: 1, “poids”:3.5}]
Objets
1
2
3
4
valeur
7
4
3.1
1
poids (kg)
17
11
9
3.5
ratio val/poids
0.41
0.36
0.34
0.29
La stratégie, sur le modèle du rendu de monnaie sera la suivante:
classer les objets dans l’ordre décroissant de leur taux de valeur (taux de valeur = valeur / masse). Ainsi le premier élément de la liste sera celui ayant le meilleur rapport valeur/masse.
on prend le premier élément de la liste, puis le deuxième, etc., tant que le sac peut encore les contenir.
Algorithme de type programmation dynamique
Nous allons chercher à adapter ici aussi l’algorithme vu pour le rendu de monnaie:
Algorithme:
rendu de monnaie
sac à dos
Pour toute valeur de montant i jusqu’à x
Pour tout poids i jusqu’à W
Pour tout montant de piece de la caisse
Pour tout objet (vi, pi) du tresor
Test 1: le montant de la piece est-il < i?
Test 1: Le poids de l’objet est-il < i?
Test 2: Si j’ajoute la piece pour rendre la monnaie, le nombre de pieces rendues sera-t-il inférieur à celui stocké pour i? (le reste de la somme à rendre a deja été calculé precedemment)
Test 2: Si je prend l’objet, le montant total rapporté est-il supérieur à la valeur stockée pour i?
Si oui: rendre la piece
Si oui: prendre l’objet
Cela reviendra à remplir le tableau suivant, de manière ascendante:
Commencer par le sac de plus petite capacité.
Pour chaque objet de poids < capacité du sac:
prendre l’objet.
Compléter le sac avec la solution optimale déjà trouvée dans le tableau.
Choisir parmi les solutions trouvées, celle de gain optimal.
Continuer avec un sac de capacité supérieure.
capacité du sac (kg)
Liste des objets (valeur,poids)
coût cumulé ($)
4, 5, 6
[(1,3.5)]
1
7,8
[(1,3.5), (1,3.5)]
2
9
..
..
10
..
..
11
..
..
12
..
..
13
..
..
14
..
..
15
..
..
16
..
..
17
..
..
18
..
..
Le problème du voyageur du commerce
énoncé du problème
le problème du voyageur de commerce, est un problème d’optimisation qui, étant donné une liste de villes, et des distances entre toutes les paires de villes, détermine un plus court circuit qui visite chaque ville une et une seule fois.
Malgré la simplicité de son énoncé, il s’agit d’un problème d’optimisation pour lequel on ne connait pas d’algorithme permettant de trouver une solution exacte rapidement dans tous les cas. Plus précisément, on ne connait pas d’algorithme en temps polynomial, et sa version décisionnelle (pour une distance D, existe-t-il un chemin plus court que D passant par toutes les villes et qui termine dans la ville de départ ?) est un problème NP-complet. Voir annexe pour précisions.
Pour résoudre ce problème, une heuristique gloutonne construit une seule solution, par une suite de décisions définitives sans retour arrière, parmi ces méthodes on cite le plus proche voisin, la plus proche insertion, la plus lointaine insertion et la meilleure insertion. Il n’est pas certain que la méthode donne la meilleure solution.
La figure suivante aide à la resolution. La solution optimale est celle qui va joindre tous les noeuds du graphe, une seule fois. (Cycle hamiltonien)
Des solutions possibles, mais non optimales sont celles qui permettent de visiter tous les noeuds une seule fois, mais dont la distance parcourue cumulée n’est peut-être pas la plus courte.
illustration de la recherche d'un cycle hamiltonien dans un graphe.
Mais une illustration plus concrête est celle par exemple du problème de la tournée du candidat pour les élections présidentielles aux état-unis:
tournée du candidat à la presidentielle
On voit que la recherche d’une solution en comparant tous les tours qu’il est mathématiquement possible de faire n’est pas raisonnable. La complexité est trop importante.
Exemple: solution gloutonne
Un voyageur cherche un itinéraire passant par toutes les villes du tableau, et qui minimise la distance totale parcourue. Les villes peuvent être visitées dans n’importe quel ordre mais aucune ne doit être négligée, et le visiteur doit revenir à la fin à sa ville de départ.
Le voyageur part de Nancy et souhaite visiter Metz, Paris, Reims et Troyes, avant de retourner à Nancy.
Voici un tableau donnant les distances kilométriques entre chacune des ces villes.
Nancy
Metz
Paris
Reims
Troyes
Nancy
55
303
188
183
Metz
55
306
176
203
Paris
303
306
142
153
Reims
188
176
142
123
Troyes
183
203
153
123
Quelle est la stratégie gloutonne à mettre en oeuvre ?
Mettez en oeuvre cette stratégie et donnez la solution.
Calculez la distance totale pour le parcours Metz - Reims - Paris - Troyes (départ et arrivée à Nancy sous-entendus)
Que dire de la solution gloutonne ?
Méthode itérative d’amélioration: algorithme de recherche locale k-opt
L’algorithme k-opt est un algorithme de recherche locale proposé par Georges A. Croes en 19581 pour résoudre le problème du voyageur de commerce en améliorant une solution initiale. On représente le tour par un graphe connexe.
à chaque étape, on supprime deux arêtes de la solution courante et on reconnecte les deux tours ainsi formés. Cette méthode permet, entre autres, d’améliorer le coût des solutions en supprimant les arêtes sécantes lorsque l’inégalité triangulaire est respectée (voir figure ci-contre). Sur le schéma de droite, la route {a, b, e, d, c, f, g} est changée en {a, b, c, d, e, f, g} en inversant l’ordre de visite des villes e et c. Il n’est toutefois pas certain que la solution trouvée soit également optimale lorsque l’on additionne ces morceaux de tours.. source: wikipedia: 2-opt.
Plus généralement, lorsqu’on inverse l’ordre de parcours de deux villes, il faut aussi inverser l’ordre de parcours de toutes les villes entre ces deux villes.
Résumé. L’essentiel à retenir
Programmation dynamique
L’idée de la programmation dynamique, c’est de gagner en efficacité. On cherche à reduire la complexité temporelle et spatiale.
Les problèmes à resoudre:
peuvent être décomposés en sous-problèmes
présentent un chevauchement des sous-problèmes.
Par exemple, pour la suite de Fibonacci, ou le triangle de Pascal, les coefficients de la suite ou du triangle sont calculés à partir des précédents, ceux de rang inférieur(sous problèmes). En stockant ces valeurs dans une liste, on peut les réutiliser sans les calculer à nouveau.
Algorithmes gloutons
Un algorithme glouton dépend du problème que l’on cherche à resoudre. Il n’y a pas d’algorithme glouton universel. Il permet de trouver une solution à un problème d’optimalité. Il part du principe que l’on peut trouver une solution approchante pour un problème NP-complet, en utilisant une stratégie et en faisant des choix. Chacun de ces choix semble être le meilleur sur le moment.
Les choix realisés sont:
rendre la piece de monnaie la plus grande possible, d’abord.
prendre l’objet de plus grand ration prix/poids, d’abord.
Programmation dynamique
Il s’agit maintenant d’une stratégie ascendante, utilisant des résultats optimum, établis pour de plus petit cas, afin de resoudre de plus gros.
pour le rendu de monnaie: commencer par résoudre le problème d’optimalité pour rendre de plus petites sommes. Puis, on utilise cette solution pour rendre une partie des sommes plus importantes.
pour le problème du sac à dos: de commencer par remplir un sac de plus petite contenance. Puis, on utilise ce résultat pour compléter de plus gros sacs.
On fait des choix à chaque étape, mais selon une stratégie bien définie, et qui ne change plus, en esperant que la somme des solutions intermédiaires va donner finalement une solution optimale. Mais on n’en est pas sûr. Et on ne revient pas en arrière.
Algorithme avec recherche locale
Pour le problème du TSP (Traveling salesman problem, ou problème du voyageur du commerce), on peut utiliser un algorithme de recherche locale, comme le k-opt. Celui-ci va cette fois remettre en doute les choix précédents.
Les étapes et leurs liens peuvent être représentés par un graphe connexe.
L’un des algorithmes existant pour la resolution, le 2-opt, va rechercher un minimum local pour un morceau de tour constitué de quelques noeuds. L’algorithme procède par permutation des arêtes entre noeuds. Et il conserve le morceau de tour de plus courte distance.
Il s’agit d’une succession de choix qui determine la solution.
Le k-opt est une méthode itérative d’amélioration. Elle est souvent utilisée après une phase constructive (qui peut être gloutonne) pour affiner le résultat. le k-opt s’arrête quand il ne peut plus améliorer la solution immédiate, mais cela ne garantit pas que c’est la meilleure solution absolue. (illustre la notion d’optimum local vs optimum global)
Complexité
Rappels
Complexité temporelle d’un algorithme. Il s’agit du nombre d’opérations élémentaires executées par l’algorithme dans un pire cas (une instance en entrée qui demande le plus de calculs). Cette complexité est exprimée en fonction de la “taille de l’entrée”. Par exemple, nous avons vu des algorithmes de tri avec des complexité en O(n2) ou en O(nlogn) avec n la longueur du tableau en entrée.
Pour l’exemple du voyageur du commerce: Le nombre de solutions possibles, où les villes sont toutes parcourues une fois, il y a un nombre TRES élevé d’alternatives:
Supposons un graphe à 50 sommets qui représente la carte de ces villes. Il y a 49! possibiltés. Ce qui fait 6,08.1062 solutions.
Si l’ordinateur évalue une solution en 0,1 ms, cela fait 6,08.1058s, soit 1,9.1049 siecles de calculs !! (L’Univers a 14 milliards d’années).
Les algorithmes des problèmes de décision sont classés selon leur complexité:
Problèmes P: probleme faciles à trouver
Un problème est dit polynomial si il existe un algorithme pour le résoudre dont la complexité peut s’exprimer comme un polynôme de la taille de l’entrée. L’ensemble des problèmes polynomiaux est noté P et est considéré comme un ensemble de problèmes “faciles” (ils peuvent être résolus relativement efficacement).
Un exemple de problème polynomial est celui de la connexité dans un graphe. Étant donné un graphe à n sommets (on considère que la taille de la donnée, donc du graphe, est son nombre de sommets), il s’agit de savoir si toutes les paires de sommets sont reliées par un chemin. Un algorithme de parcours en profondeur construit un arbre couvrant du graphe à partir d’un sommet. Si cet arbre contient tous les sommets du graphe, alors le graphe est connexe.(wikipedia)
Problèmes NP: problèmes faciles à vérifier
Une autre classe de problèmes importante est celle des problèmes dont on peut tester en temps polynomial si une solution est valide (par exemple, je vous donne un tableau et vous devez non pas le trier mais me dire si il est déjà trié ou non). Cette classe s’appelle NP pour Non déterministe Polynomial.
Supposons que vous soyez chargé de loger un groupe de quatre cents étudiants. Le nombre de places est limité, seuls cent étudiants se verront attribuer une place dans la résidence universitaire. Pour compliquer les choses le doyen vous a fourni une liste de paires d’étudiants incompatibles, et demande que deux étudiants d’une même paire ne puissent jamais apparaître dans votre choix final.wikipedia.
Produire une telle liste à partir de zéro paraît tellement difficile qu’elle en est même impraticable, car le nombre de façons de regrouper cent étudiants parmi quatre cents dépasse le nombre d’atomes de l’univers !. Par contre, une fois que l’on vous fournit une solution, il est facile de montrer que celle-ci est juste ou fausse.
Si un problème est connu comme étant NP et si une solution au problème est connue, la démonstration de l’exactitude de la solution peut toujours être réduite à une vérification P (temps polynomial). Les algorithmes de cette classe sont non déterministes.
Existe t-il pour les problèmes connus de la classe NP un algorithme susceptible de trouver une solution et de complexité polynomiale. On n’en est pas sûr. Peut-être que cette apparente difficulté ne fait que refléter le manque d’ingéniosité de nos programmeurs.
Le problème de savoir si P = NP est un des problèmes du millénaire de l’institut de mathématiques Clay. Informellement, il s’agit de savoir si vérifier efficacement qu’une “solution à un problème est bien une solution valide” revient à “pouvoir trouver efficacement une solution valide au problème.”
Problèmes NP-complets
Les problèmes dits NP-complets sont des problèmes au moins aussi difficiles que les plus difficiles de la classe NP.
source: page P=NP wikipedia
Exemples: le voyageur du commerce, le calcul de solutions optimales en économie (enoncé semblable mais à une echelle plus grande que celui du sac à dos), ou dans les processus de fabrication ou de transport…
Tous les algorithmes connus pour résoudre des problèmes NP-complets ont un temps d’exécution exponentiel en la taille des données d’entrée dans le pire des cas, et sont donc inexploitables en pratique même pour des instances de taille modérée.
Les classes P, NP, NP-complet ne concernent stricto sensus que les problèmes de décision. Donc quand on dit que le problème du voyageur de commerce est NP-complet, il faut l’entendre : dans sa version « décisionnelle », qui est : est-il possible de trouver un chemin qui passe par toute les villes et qui soit de longueur inférieure à L? De manière générale, tous les problèmes d’optimisation sous contrainte, comme ceux vus plus haut, sont aussi des problèmes de décision.
Trouver un algorithme qui résout un problème NP-complet, comme le problème du voyageur de commerce, en temps polynomial, suffirait à démontrer que P = NP, ce serait alors toute une série de problèmes très importants qui se trouveraient résolus. Sans exhiber un algorithme, une preuve pourrait donner des indices précieux pour construire un tel algorithme. wikipedia.
Annexes
Programmes python du rendu de monnaie
algo naîf vu en classe de 1ere
defestvide(ensemble):"""
fonction qui teste si un ensemble est vide
retourne True si vide
False sinon
"""vide=Trueforiinensemble:vide=Falsereturnvidedefrendre(cost,caisse):"""
fonction qui rend la monnaie sur une somme cost (int) selon le
contenu de la caisse (une variable de type set)
en commençant par la plus grande des pieces.
caisse : la caisse du commerçant (set)
rendu : ce que rend le commerçant (dict)
à chaque itération de la boucle, on retire la piece de l'ensemble caisse
qui est utilisée jusqu'à ce que caisse soit vide
"""### initialisation ###rendu={}foriincaisse:rendu[i]=0whilenotestvide(caisse):piece=max(caisse)n=cost//piececost=cost-n*piecerendu[piece]=ncaisse.remove(piece)returnrendu
essais
>>>caisse={1,2,5,10,20,50}>>>rendre(93,caisse)# OK optimal{1:1,2:1,5:0,10:0,20:2,50:1}>>>caisse={1,10,15}>>>rendre(21,caisse)# non optimal{1:6,10:0,15:1}
algo glouton recursif
(non donné)
algorithme en programmation dynamique
importcopydefrenduMonnaieProgDyn(x,c):"""
c : caisse avec les genres de pieces à rendre par ex [1,2,5,10]
x : montant à rendre
res : tableau contenant : [nbe pieces rendues,[nb pieces de pieces de A, nb de B, nb de C]]
temp : nombre de pieces rendues
"""n=len(c)res=[[x,[0forjinrange(n)]]foriinrange(x+1)]# initialisation de la table avec des x # x pieces rendues correspond à la plus mauvaise des reponses (par ex que des pieces de 1)res[0][0]=0foriinrange(1,x+1):# valeur du montant à rendre : recherche pour TOUT montantforjinrange(n):# parcours de la caisseifi>=c[j]:# rendre de la monnaie avec cette piecetemp=1+res[i-c[j]][0]# rend une piece du type de celle de rang j# le nbe de piece au total est egal à 1 + le nbe de piece pour rendre le reste (deja calc)ifres[i][0]>=temp:res[i][0]=temp# nombre de pieces renduesres[i][1]=copy.deepcopy(res[i-c[j]][1])# copier le nb de pieces de A , de B, de C pour le rendu de monnaie# monnaie du montant i-c[j]# ici il faudra copy.deepcopy pour faire une copie par valeurres[i][1][j]+=1# ajouter 1 au nombre de pieces de c[j] utiliséesprint(f'i: {i:2}, j: {j:2}, res[{i}]: {res[i]}, temp: {temp}')returnres[x]
Algorithme exhaustif
Programme utilisé pour determiner toutes les combinaisons possibles de rendu de monnaie. Complexité exponentielle…
defrendu_expo(somme,caisse,rendu=[]):ifsomme==0:solutions.append(sorted(rendu,reverse=True))foriinrange(len(caisse)):ifcaisse[i]<=somme:rendu_expo(somme-caisse[i],caisse[i:],rendu+[caisse[i]])else:rendu_expo(somme,caisse[1:],rendu)defunique(L):# pour eliminer les doublons de la listeT=[]T.append(L[0])forsolinL:ifsolnotinT:T.append(sol)returnTsolutions=[]rendu_expo(53,[30,24,12,6,3,1])solution_min=unique(solutions)print(len(solution_min))solution_min
Le problème du sac à dos
Résolution
importcopydefsacADosRemise(W,s):n=len(s)res=[[0,[0forjinrange(n)]]foriinrange(W+1)]# format [valeur totale,[nb_o1, nb_o2, nb_o3, nb_o4]]]foriinrange(1,W+1):j=0while(j<n)and(i-s[j][1]>=0):ifres[i-s[j][1]][0]+s[j][0]>res[i][0]:res[i][0]=res[i-s[j][1]][0]+s[j][0]res[i][1]=copy.deepcopy(res[i-s[j][1]][1])res[i][1][j]+=1j+=1returnres[W]
essais:
>W=15>s=[(1,2),(2,3),(4,5),(6,8)]# ensemble de couples (valeur, poids)>sacADosRemise(W,s)[12,[0,0,3,0]]
Liens
page de cours NSI sur les algorithmes de complexité exponentielle, et la programmation dynamique cours de qkzk
Dans le chapitre précédent, sur la complexité, l’objet d’étude principal etait l’algorithme. On en a fait une mesure de son efficacité: un algorithme est plus efficace s’il est plus rapide (donc de classe de complexité plus faible).
En calculabilité, le problème devient l’objet central.
Voir le cours d’algorithmique de Pierre Antoine Champin, CNRS: definition très claire de la notion de Problème comme une classe.
Le Problème de Décision - Voyages au pays des maths | ARTE
On a souvent l’impression que pour chaque problème on peut trouver un algorithme de solution. Ce n’est pas le cas : pour des nombreux probèmes naturels et intéressants il n’existe pas d’algorithme. Ces problèmes sont non calculables. Cette notion a évolué dans l’histoire de l’informatique au cours des étapes suivantes:
Charles Babbage (1791 – 1871), professeur à Cambridge, construit la machine différentielle et la machine analytique. La dernière peut être considérée comme précurseur des ordinateurs modernes, consistant d’une unité de contrôle, une unité de calcul, une mémoire, ainsi que l’entrée-sortie.
Charles Babbage (1791 – 1871) - wikipedia
Ada Lovelace (1815 – 1852) travaille avec Babbage et préconise l’utilisation de la machine analytique pour la résolution de problèmes mathématiques. C’est le premier langage informatique, énoncé avant même l’existance d’une machine. Elle est considérée comme premier programmeur du monde.
Ada Lovelace (1815 – 1852)
David Hilbert (1862 – 1943), professeur à Göttingen, présente en 1920 un programme de recherche visant à clarifier les fondaments des mathématiques : “tout enoncé mathématique peut être soit prouvé soit refuté”. Plus tard il enonce le “Entscheidungsproblem” : On doit pouvoir montrer de façon “mécanique” si un enoncé mathématique est vrai ou faux.
Pour cela, on s’appuie sur un systèmes d’axiomes censés fonder les mathématiques. A partir de ce système d’axiomes, on n’aura jamais des démonstrations contradictoires d’une proposition (d’un problème, d’un énoncé de mathématique).
Selon lui, tout est décidable, selon le terme qui sera employé plus tard.
David Hilbert (1862 – 1943)
Kurt Gödel (1906 – 1978), un des logiciens les plus fameux de l’histoire, répond en 1931 négativement quand au programme proposé par Hilbert. Il affirme qu’un systeme logique, aussi puissant soit-il, admet des propositions (des problèmes) ne pouvant être ni infirmées ni confirmées à partir des axiomes de la théorie. Ces propositions sont qualifiées d’indécidables.
Il s’agit du théorème d’incomplétude.
Paradoxalement, on sait que certaines de ces propositions indécidables sont vraies, mais on ne peut le démontrer.
Kurt Gödel (1906 – 1978)
Alan Turing (1912 – 1954) et
Turing cherche s’il n’y aurait pas au moins une procédure mécanique pour trouver quelles sont les propositions que l’on peut effectivement déduire d’un système d’axiomes, c’est à dire de décider de leur vérité (équivalent du problème de décision). Il part du principe que ce qu’un humain peut déduire est équivalent à ce qu’une machine peut déduire. Ainsi, il suffit de décrire convenablement une machine idéale pour préciser ce qu’est une procédure systématique. Cette machine idéale sera la machine de Turing. Il montre, par un raisonnement logique que cette machine ne peut pas démontrer toutes les propositions d’un système d’axiomes (indécidabilité).
Alan Turing (1912 – 1954) - wikipedia
Définitions
Qu’est ce qu’un problème?
Informatiquement, problème sera synonyme de fonction. Un problème est caractérisé par:
Le nom du problème
des données d’entrée, que l’on appelle instance du problème.
une question mathématique posée sur ces données d’entrée.
Rq : Ne pas confondre problème et algorithme le résolvant. Il peut y avoir plusieurs algorithmes qui resolvent le même problème (calculent la même fonction).
Les problèmes s’énoncent de la manière la plus générale possible. On peut les désigner comme des classes, possédant de multiples instances (celles pour lesquelles on place des valeurs à la place des varaibles).
Problème 1
Donnée : Un ensemble N d’entiers naturels
Question : Déterminer les nombres pairs dans cet ensemble.
Instance 1: Quels sont les nombres pairs dans l’ensemble [1,2,3,4]?
Problème 2
Donnée : Un ensemble N d’entiers naturels
Question : Déterminer les nombres premiers de cet ensemble.
Instance 2: Le nombre 137 est-il premier?
Problème 3
Donnée : Un programme C.
Question : Le programme est-il syntaxiquement correct ?
Ce dernier exemple de problème suggère qu’un algorithme est une
donnée comme une autre. En effet, le script qui traduit l’algorithme est écrit dans un langage. Et la machine va le lire et l’interpréter à l’aide d’un autre programme. Pour ce programme, le script est une donnée (interpréteurs, compilateurs).
Calculabilité
Qu’est-ce que c’est “calculable”?
En mathématique : Une fonction f : ℕ
→ ℕ est calculable s’il existe un programme/algorithme qui calcule f: si la fonction f est définie sur une entrée x, alors l’algorithme doit renvoyer la valeur f(x), et si f n’est pas définie, l’algorithme doit boucler sur l’entrée x.
En algorithmique: on dira qu’une fonction est calculable si elle peut être programmée dans l’un ou l’autre des langages de programmation usuels.
La première fonction explicite non calculable a été décrite par Turing en 1936. Il s’agit du problème de l’arrêt : étant donné un algorithme A et une entrée x, il s’agit de déterminer si A s’arrête ou non sur l’entrée x (i.e A ne boucle pas sur l’entrée x).
Théorème : Le problème de l’arrêt est incalculable.
Qu’est ce que la “terminaison”? On dit qu’un programme termine s’il ne boucle pas, c’est-à-dire qu’il renvoie bien un résultat.
Problèmes de décision décidables
Problèmes de décision
Il existe une catégorie de problèmes que l’on appelle : problèmes de décision. Dire que le problème est decidable, c’est dire qu’il existe un programme Python permettant de calculer f(n) pour tout entier n, en un temps fini.
Ou bien : P est décidable s’il existe un algorithme qui pour chaque x dit “OUI” ou “NON” à la question : “Est-ce que P(x) est vrai ?”.
Tous les problèmes mathématiques (voir plus haut) peuvent être énoncés comme des problèmes de décision: voir page wikipedia., avec le Passage de problème d’optimisation à problème de décision.
Pour les problèmes 1 et 2 vus auparavent, on peut les énoncer sous la forme:
instance du Problème 1
Donnée : Un nombre entier positif n en base 2.
Question : n est-il pair?
autre exemple:
instance du Problème 2
Donnée : Un nombre entier positif n en base 10.
Question : n est-il premier?
Les problèmes 1 et 2 sont énoncés comme un problème de décision.
En conséquence, le problème de la décision, c’est-à-dire la recherche d’une procédure qui indique dans chaque contexte, et au bout d’un temps fini, si une propriété est vraie ou fausse, est équivalent à la construction d’un algorithme qui calcule pour chaque fonction f et pour chaque argument x de f, la valeur y telle que y = f(x). Autrement dit, le problème de la décision est équivalent au problème du calcul.
décidables ou indécidables?
Les fonctions, ou propriétés bien énoncées1 en langages mathématique sont-elles toutes décidables? La reponse est : Non, il n’existe pas de telle méthode, comme cela a été démontré en 1931 par Kurt Gödel (voir plus haut).
L’indecidabilité c’est l’impossibilité absolue et définitivement démontrée de résoudre par un procédé général de calcul un problème donné.
Imaginons qu’il existe des programmes qui calculent si un programme termine. Ces programmes prendraient une fonction A comme paramètre, et une donnée x d’entrée de cette fonction.
Si A s’arrête sur l’entrée x, le programme termine peut renvoyer True. Mais si ce n’est pas le cas, le programme ne répondra jamais. À quel moment décide-t-on qu’il n’a pas encore répondu, c’est qu’il ne répondra jamais ? On n’a aucun moyen de le faire, et c’est ce que prouve le théorème de Turing.
Décidabilité et indécidabilité : Problème de l'arrêt | Rachid Guerraoui
Exemple de problème non décidable :
Problème
Donnée : Un programme C.
Question : Le programme s’arrête-t-il toujours ?
Preuve d’un algorithme
terminaison et correction
Prouver le bon fonctionnement d’un algorithme nécessite de vérifier deux propriétés :
premièrement : la terminaison : prouver que l’algorithme se termine.
deuxièmement : la correction : si l’algorithme se termine, il fait bien ce qu’on attend de lui (correction partielle).
D’après ce qui a été vu auparavent, il n’EXISTE PAS d’algorithme capable de calculer la terminaison ou la correction d’un programme. Ce sera à vous de PROUVER un algorithme, à partir de méthodes exposées ici.
méthodes pour les algorithmes itératifs
Pour la terminaison : étude du VARIANT de boucle
Il faudra exhiber, pour chaque boucle while, un VARIANT de boucle.
Pour la correction :
Exhiber un INVARIANT de boucle qui permet de montrer le résultat voulu.
Invariant de boucle :
on appelle invariant d’une itération toute propriété, vraie à l’initialisation, et qui demeure conservée quand on passe d’un état quelconque à son successeur.
Algorithme recursif
Dans le cas des algorithmes récursifs, ces méthodes sont spécifiques.
terminaison
Le (ou l’un des) paramètre(s) appelé(s) par la fonction recursive doit avoir une relation d’ordre descendante. C’est à dire que ce paramètre doit être de plus en plus petit à chaque appel de la fonction dans le corps de la fonction récurente.
correction partielle
Il faut montrer que si les appels internes à l’algorithme font ce qu’on attend d’eux, alors l’algorithme entier fait ce qu’on attend de lui. La preuve de correction se fait à partir d’une demonstration par recurrence :
On commence à établir la preuve pour le rang n = 0, puis n = 1.
il faut montrer que si on peut prouver la correction pour une suite de rang n-1, on aboutira à la preuve de correction pour une suite de rang n.
Exemples
Exemple 1: fonction somme
Script
La fonction suivante réalise la somme des termes d’une liste.
Le script contient une boucle bornée. La variable k augmente d’une unité à chaque itération. De k=0 jusqu’à len(L)-1. La boucle s’arrêtera lorsque k atteindra len(L) -1, ce qui arrivera forcement.
correction
On considère l’invariant de boucle énoncé ainsi : “pour un indice k, s est égal à la somme de L[:k]”. C’est à dire à:
L[0] + L[1] + L[2] + … + L[k-1]
A l’entrée dans la boucle : s = 0. Ce qui est attendu puisque l’on n’a pas encore additionné le premier terme L[0].
Pour une valeur k. On suppose que s est egal à la somme des termes de L[:k-1]. Alors, à la ligne 4, on ajoute L[k] à s. Donc s est bien égal à la somme de L[:k].
A la fin de la boucle, k vaut len(L)-1, et c’est justement l’indice du dernier élément de la liste. s sort alors avec pour valeur la somme de TOUS les termes de la liste L. CQFD
Exemple 2: Recherche dichotomique
Definition
La recherche dichotomique consiste à diviser par 2 l’ensemble de recherche. Pour cela, on définit le milieu de l’intervalle de recherche, puis on conserve:
T[borne_inf : milieu] si T[milieu] > x
T[milieu : borne_sup] si T[milieu] < x
Exemple: On recherche un mot commençant par la lettre c dans le dictionnaire. Les lettres du dictionnaire sont dans l’ensemble [a .. z]. Il s’agit d’une liste [‘a’,‘b’,‘c’,’d’, ..’m’, ..,‘x’,‘y’,‘z’].
Comme il s’agit d’une liste dont les indices vont de 0 à 25: Le milieu, c’est 25//2 soit 12. la lettre c a un rang inférieur à 12 (lettre m). Donc, dans une première étape de recherche, on prendra la liste entre les rangs 0 et 12 pour rechercher c.
defrecherche_dicho(T,x):"""
:param T: sorted list of elements
:param x: element
:return: int, index of x in the list
else -1
"""i_min=0i_max=len(T)-1while(i_max>=i_min):mid=(i_min+i_max)//2ifT[mid]==x:returnmidelifT[mid]<x:i_min=mid+1else:i_max=mid-1return-1
Terminaison de la fonction de recherche dichotomique
Dans le pire des cas, l’intervalle va se réduire jusqu’à se limiter à un seul élément. Celui dont l’index est mid. Avec i_min == i_max
Si l’élément recherché est dans la liste: Cet élément est alors la valeur recherchée x, et la fonction se termine en retournant la valeur de l’index de x dans la liste, mid.
Si l’élément recherché n’est pas dans la liste: alors, soit i_min prend la valeur de mid+1, soit i_max prend la valeur de mid-1. On a alors i_min > i_max, qui est la condition d’arrêt de la boucle.
Efficacité de la recherche dichotomique
Le nombre d’opérations de comparaison, dans le pire des cas, est proportionnel à log(N). N étant égal à la taille de la liste. Et log(N) étant egal au nombre de divisions par 2 qu’il faut effectuer pour que N arrive à 1:
Un Problème: Ensemble Nom + Données d’entrée + Question
Pour la suite: Problème = Fonction
L’ensemble des algorithmes, donc des fonctions calculables, est dénombrable. Un algorithme est une approche étape par étape pour résoudre un problème.
L’ensemble des fonctions est indénombrable, donc il existe des fonctions incalculables.
Calculable: il existe une fonction f programmable dans un langage courant (python)
Calculable = Décidable: un problème calculable peut être traduit en un problème équivalent décidable. La différence est que, pour un problème calculable, on doit calculer une image f(x), alors que pour un problème décidable, la fonction retourne une valeur booléenne (True,False). Le problème est exprimé différemment.
Indécidable (ou incalculable): c’est l’impossibilité définitivement démontré de résoudre par un algorithme un problème donné.
Le problème de l’arrêt est un exemple de fonction incalculable.
L’étude de la terminaison d’une fonction est liée à l’étude de sa complexité. Il faut pouvoir évaluer si un problème décidable, l’est en un temps raisonnable.
Il n’existe pas de programme permettant de savoir si une fonction termine, et si elle fait bien ce qui est attendu d’elle. C’est pour cela qu’il faudra savoir prouver une fonction. Pour cela, il faudra:
démontrer que la fonction termine. On s’aide souvent d’un VARIANT de boucle.
démontrer la correction de cette fonction, c’est à dire qu’elle fait bien ce que l’on attend d’elle. On s’aide souvent d’un INVARIANT de boucle.
ceci fait reference au theoreme de completude énoncé par Gödel. Une théorie mathématique pour laquelle tout énoncé est décidable est dite complète, sinon elle est dite incomplète. D’où le Premier Théorème d’incomplétude de Gödel
“Dans n’importe quelle théorie récursivement axiomatisable, cohérente et capable de
« formaliser l’arithmétique », on peut construire un énoncé arithmétique qui ne peut être ni prouvé ni réfuté dans cette théorie. Il n’existe donc aucune théorie mathématique complète.” (Premier Théorème d’incomplétude de Gödel) ↩︎
langages
Paradigmes des langages
Impératif
Fonctionnel
on ne trouve ni affectation (ou assignation), ni séquence (succession inconditionnelle de deux instructions).
cours POO, classe, instanciation, accesseur getter et mutateur setter
Sous-sections de langages
langages mathematiques
Langages mathematiques
Pourquoi 1 + 1 = 2 ?
Pour comprendre cette opération, il faut déjà comprendre la signification de chacun des symboles utilisés, les chiffres 1 et 2, et les opérateurs + et =
1
+
=
2
Ainsi, pour apprendre à compter à une machine, il faudra lui expliquer comment les nombres se succèdent, et quel rôle jouent chaque opérateur sur ces nombres.
Les chiffres
Les symboles des chiffres nous sont ainsi intuitifs, mais, dans l’idée d’une construction du langage mathématique, il doit exister une règle qui nous dit:
que le successeur immédiat de 1, dans l’ensemble des entiers naturels, est le 2 et non le 3. (et qu’il existe aussi la notion de predecesseur)
que le plus petit des entiers naturels est le 0
Cet article du site automaths détaille ainsi la construction de l’ensemble des entiers naturels par des axiomes.
Comment sont placés les successeurs pour
Giuseppe Peano (1858-1932) est un mathématicien et linguiste italien. Il a repertorié les caractéristiques structurelles des nombres naturels dans une liste d’axiomes énoncés dans la symbolique logique. Aujourd’hui, ces axiomes constituant le langage mathématique traitent tous les signes mathématiques et logiques, et jouent un rôle analogue à celui de la grammatisation dans les langues naturelles.
Giuseppe Peano (1858-1932)
Une fois établie la construction de l’ensemble des entiers naturels selon Peano, nous allons nous intéresser aux axiomes définissant les symboles + et =.
On y lira que 0 + 1 = 1 est l’un des axiomes définissant l’addition, et s’écrit en langage axiomatique:
$$0 + S_0 = S_0$$
L'addition: la réunion de 2 ensembles
Questions
Q1: Qui était Giuseppe Peano et qu’a-t-il cherché à montrer à propos des entiers naturels?
Q2: Qui était le mathématicien Kurt Gödel, et qu’a-t-il apporté à la théorie sur le langage mathématique initiée par Giuseppe Peano? En particulier, ce que l’on appelle la complétude d’un système d’axiomes ?
Q3: A quoi peut-on comparer un axiome mathématique? Y-a-t-il quelque chose d’équivalent dans les langues naturelles?
Q4: Qu’est ce que l’addition +?
Q5: Qu’est ce que l’égalité =? Commenter les 2 propriétés qui la définissent.
Conclusion
Les mathématiques sont formées:
d’un ensemble de valeurs, comme par exemple l’ensemble des entiers naturels $\mathbb{N}$
de relations entre les éléments de cet ensemble. Comme par exemple la relation de successeur vue plus haut.
de règles sur ces valeurs. Ces règles définissent les opérateurs sur ces valeurs.
Dans le chapitre suivant, on verra que l’on peut créer un langage mathématique pour le traitement de l’information.
Calcul propositionnel
On va avoir besoin d’ajouter aux ensembles de nombres un nouvel ensemble particulier: un ensemble contenant 2 éléments contenant les valeurs de verité vrai / faux. Cela nous permettra d’utiliser des machines pour automatiser le raisonnement. C’est à dire pour produire des démonstrations, et ainsi de prouver des propositions.
Le calcul propositionnel est un ensemble de règles permettant un nombre fini d’étapes pour démonter si une proposition est VRAIE ou FAUSSE.
Les Propositions contiennent des affirmations telles que:
le moteur est en marche
la vanne de sécurité est ouverte
la cuve fuit, etc…
On remplace ces affirmations par des symboles neutres, qui prennent l’un des 2 états: VRAI ou FAUX. Cet état est choisi pour établir une certaine cohérence avec l’information à traduire du monde exterieur (moteur en marche = VRAI, …)
Les propositions vont combiner ces affirmations à l’aide d’opérateurs logiques. Cela va constituer une formule.
Une propriété faisant intervenir n éléments offre $2^n$ interprétations envisageables.
La formule doit prendre les valeurs VRAI pour toutes les interprétations de l’énoncé.
Dans ce paragraphe, on étudie les propositions en tant que telles, et les liens qui peuvent exister entre elles, sans se préoccuper du contenu de ces propositions.
On rappelle qu’une proposition est un énoncé pouvant être Vrai ou Faux. On dit alors que les deux valeurs de vérité d’une proposition sont « vrai » et « faux ».
Equivalence logique
Définition
Deux propositions équivalentes P et Q sont deux propositions ayant les mêmes valeurs de vérité.
Cette phrase peut se visualiser dans un tableau appelé table de vérité dans lequel on fait apparaître les différentes valeurs de vérité possibles pour le couple (P, Q) (Vrai et Vrai, Vrai et Faux, …) et, en correspondance, les valeurs de vérité de la proposition P ⇔ Q. Ainsi, la table de vérité de l’équivalence logique P ⇔ Q est :
P
Q
P <=> Q
F
F
V
F
V
F
V
F
F
V
V
V
On peut ainsi lire, deuxième ligne, que si P est vraie et Q est fausse, P ⇔ Q est fausse.
L’équivalence logique joue pour les propositions, le rôle que joue l’égalité pour les nombres. Les expressions 3 + 2 et 5 ne sont pas identiques et pourtant on écrit 3+2 = 5. De même, les propositions (x2 = 1) et (x = 1 ou x = −1) ne sont pas identiques et pourtant on écrit (x2 = 1) ⇔ (x = 1 ou x = −1).
Implication
Definition
Si P et Q sont deux propositions, on définit l’implication logique : P ⇒ Q par sa table de vérité.
P
Q
P => Q
F
F
V
F
V
V
V
F
F
V
V
V
P et Q deux propositions. (P ⇒ Q) ⇔ (nonP ∨ Q).
P ⇒ Q est fausse dans l’unique cas où P est vraie et Q est fausse: si P (est vraie) alors forcément Q (est vraie aussi). Mais pas réciproquement.
Exemple: Lorsque le facteur dépose une lettre, le chien aboie. Parmi les interprétations envisageables pour cet énoncé, il se peut que le chien aboie alors que le facteur n’a PAS deposé de lettre.
Négation d’une proposition
Soit P une proposition. On définit sa négation, notée nonP (ou ⌉P), à partir de sa table de vérité.
P
nonP
V
F
F
V
Exemple: Je ne lave pas mon linge (nonL ou -L) s’il pleut (P)
On peut exprimer cette proposition à partir des affirmation L (je lave mon linge) et P (il pleut), à l’aide de l’opérateur implication => :
$$P \Rightarrow -~L$$
Les connecteurs logiques « ET » et « OU »
Soient P et Q deux propositions. On peut définir les propositions « P ou Q », notée P ∨ Q, et « P et Q », notée P ∧ Q par les tables de vérité ci-dessous.
P
Q
P ∧ Q
P ∨ Q
F
F
F
F
F
V
F
V
V
F
F
V
V
V
V
V
Remarque: Le connecteur logique OU n’a pas le sens du OU exclusif. En effet, on peut voir que lorsque P est vraie et Q est vrai, alors P∨Q est vraie
Combinaisons de propositions
Tout énoncé peut s’écrire en utilisant uniquement la conjonction ∧ et la négation (par exemple, P ⇔ Q est la proposition non(P ∧ nonQ) ∧ non(Q ∧ nonP)). Ce résultat a une importance en électronique et en informatique.
Un problème mathématique
En classe de mathématiques, un problème mathématique comprend un énoncé (la description d’un situation) suivi d’une ou plusieurs questions. Il est généralement demandé pour répondre aux questions posées d’effectuer des calculs avec les données contenues dans l’énoncé.
Toute question ne peut pas forcément s’énoncer dans un langage mathématique.
En informatique, pour un problème donné, on cherche à trouver une procédure pour le résoudre. On doit pouvoir traiter cette procédure à l’aide d’une machine. Si cette procedure existe, et si le nombre d’actions réalisées par la machine n’est pas infini, alors le problème peut être résolu. (fonction calculable selon les données de l’énoncé).
Exercices sur les procédures de calcul
Ex 1: Trouver une procédure pour calculer 2 + 3
On utilisera uniquemement les propositions suivantes:
les entiers naturels s’expriment selon la théorie axiomatique vue en classe: SS0 succede à S0 qui succede à 0…
définitions axiomatique de l’addition
variables
On considère qu’il existe une fonction d’affichage
Ex 2: Trouver une procédure pour calculer 3 - 2
Mêmes outils que pour l’exercice 1. La relation de prédecesseur est également connue.
Exercices sur le calcul propositionnel
Exercice 1: Le Soleil brille
En utilisant les affirmations S (le soleil brille), P (il pleut), B (il bruine), A (il y a un arc en ciel), O (il a un vent d’Ouest), E (il y a du vent d’Est), traduire dans la logique des propositions suivantes:
La bruine est une forme de pluie.
S’il pleut et que le soleil brille en même temps, alors il y a un arc en ciel.
Si le vent d’ouest amène la pluie, on n’a jamais vu qu’un vent d’est soit porteur de pluie.
Exercice 2:
Représenter dans le formalisme de la logique des propositions les théorèmes de géométrie suivants:
Si un triangle est équilatéral alors il est isocèle.
Un triangle rectangle n’est jamais équilatéral.
Un carré est à la fois un parallélogramme et un rectangle.
Un losange n’est ni un quadrilatère rectangle ni un triangle.
Exercice 3:
Lors de ses aventures au pays des merveilles rapportées par Lewis Carroll, Alice est souvent accompagnée par le chat de Cheshire. Ce félin énigmatique s’exprime sous la forme d’affirmations logiques qui sont toujours vraies. Alice se trouve dans un corridor dont toutes les portes à sa taille sont fermées. La seule porte ouverte est nettement trop petite pour qu’elle puisse l’emprunter. Une étagère est fixée au-dessus de cette porte. Le chat dit alors à Alice: «L’un des flacons posés sur cette étagère contient un liquide qui te permettra de prendre une taille plus adéquate. Mais attention, les autres flacons peuvent contenir un poison fatal.»
Trois flacons sont effectivement posés sur l’étagère. Le premier est rouge, le second jaune, le troisième bleu. Une étiquette est collée sur chaque flacon. Alice lit l’inscription figurant sur chaque étiquette:
Flacon rouge: le flacon jaune contient un poison; le bleu n’en contient pas;
Flacon jaune: si le flacon rouge contient un poison, alors le bleu aussi;
Flacon bleu: je ne contiens pas de poison.
Nous noterons R, J et B les variables propositionnelles correspondant au fait que les flacons rouge, jaune et bleu contiennent un poison.
Nous noterons $I_R$, $I_J$ et $I_B$ les propositions correspondant aux inscriptions sur les flacons rouge, jaune et bleu.
On résoudra les questions suivantes en utilisant une table de vérité.
Exprimez les formules $I_R$, $I_J$ et $I_B$ sous la forme de formules dépendant de R, J et B.
Les inscriptions sur les trois flacons sont-elles compatibles?
Si les trois inscriptions sont vraies, est-ce qu’un ou plusieurs flacons contiennent un poison?
Dans le cas où aucun des trois flacons ne contient un poison, est-ce qu’une ou plusieurs inscriptions sont fausses?
Les mathématiques actuelles sont bâties de la façon suivante :
on part d’un petit nombre d’affirmations, appelées axiomes, supposées vraies à priori (et que l’on ne cherche donc pas à démontrer) ;
on définit ensuite la notion de démonstration (en décidant par exemple de ce qu’est une implication, une équivalence…) ;
on décide enfin de qualifier de vraie toute affirmation obtenue en fin de démonstration et on appelle « théorème » une telle affirmation (vraie).
A partir des axiomes, on obtient donc des théorèmes qui viennent petit à petit enrichir la théorie mathématique. En raison des bases (les axiomes) non démontrées, la notion de « vérité » des mathématiques est sujette à débat.
Axiome. Un axiome est un énoncé supposé vrai à priori et que l’on ne cherche pas à démontrer.
Ainsi, par exemple, Euclide a énoncé cinq axiomes (« les cinq postulats d’Euclide »), qu’il a renoncé à démontrer et qui devaient être la base de la géométrie (euclidienne). Le cinquième de ces axiomes a pour énoncé : « par un point extérieur à une droite, il passe une et une seule droite parallèle à cette droite ».
Aujourd’hui, ces axiomes constituant le langage mathématique traitent tous les signes mathématiques et logiques, et jouent un rôle analogue à celui de la grammatisation dans les langues naturelles.
Proposition (ou assertion ou affirmation). Une proposition est un énoncé énoncé auquel on peut attribuer une valeur de vérité vrai ou faux. Par exemple, « tout nombre premier est impair » et « tout carré de réel est un réel positif » sont deux propositions. Il est facile de démontrer que la première est fausse et la deuxième est vraie. Le mot proposition est clair : on propose quelque chose, mais cela reste à démontrer. Une proposition est construite à partir des axiomes du langage.
Théorème. Un théorème est une proposition vraie (et en tout cas démontrée comme telle). On utilise aussi en informatique le terme d’assertion pour une proposition vraie.
Définition: souvent équivalent à axiome
Conjecture: proposition que l’on suppose vraie sans parvenir à la démontrer. (et qu’il est peut être impossible de démontrer).
Un TP1 avec les exercices classiques sur la recursivité: Lien
Un TP2 avec le tracé de dessins recursifs (Turtle): Lien
Récursivité
Principe
Un algorithme récursif est un algorithme qui fait appel à lui-même dans le corps de sa propre définition. Ce principe est aussi appelé : de l’autoréférence. (traité dans la partie autres applications de la page 2 du cours).
Cependant, cette premiere definition pourrait faire penser qu’une fonction récursive va s’appeler indéfiniment, et créer sans arrêt les mêmes figures, ou les mêmes traitements.
Ce n’est pas tout à fait cela.
Pour une fonction récursive, il y a plus que de la simple autoréférence:
Il y a transmission de valeurs entre 2 étapes de la pile d’appels recursifs.
Une valeur va remonter d’un niveau $n$ vers le niveau $n-1$ qui l’a appelé.
On remonte la pile d’appels parce que la fonction contient une condition de fin (appelée condition de base).
enfin, les traitements ne sont pas tous identiques parce les arguments de la fonction changent à chaque nouvel appel recursif.
Analyse d’un exemple: itératif => récursif
Considérons une fonction ajoute2_iter qui prend N comme paramètre, et qui ajoute N fois 2.
Algorithme itératif
Supposons que nous souhaitions éviter la multiplication. L’algorithme itératif utilisera alors une boucle bornée:
defajoute2_iter(N):"""ajoute 2 un nombre N de fois
"""s=0foriinrange(N):s=s+2returns
Résultat
>>> ajoute2_iter(4)
8
Algorithme récursif
Rappel de math: Une suite est une succession ordonnée d’éléments, comme par exemple 1, 2, 4, 8, 16. On s’interesse ici à une suite en définissant un terme à l’aide du terme précédent. (suite récurente)
exemple de duite recursive, exprimée en langage mathématique
(a) Pour calculer le terme de rang n d’une suite, on définit un cas de base, un démarrage avec le premier terme de la suite:
$$u_0 = 0$$
Dans la fonction, ce demarrage vient avec le système d’instructions:
if N==0 :
return 0
(b) Puis vient la relation de récurence sur les éléments de la suite $u_n$:
$$u_{n+1} = 2 + u_n$$
ou encore:
$$u_{n} = 2 + u_{n-1}$$
On va adapter cette dernière relation dans l’appel de la fonction: return 2 + ajoute2(N-1)
Le script entier est alors:
defajoute2(N):"""fonction qui s'appelle elle-meme N fois
"""ifN==0:return0else:return2+ajoute2(N-1)
Cette succession d’appels peut se resumer par une pile d’appels, où les éléments sont mis de bas en haut, les uns après les autres lors des appels recursifs successifs:
Puis, après le return 0, la valeur 0 est retournée à ajoute2(1) = 2 + 0, qui retourne 2.
La valeur 2 est retournée à ajoute2(2). Au cours de cette descente dans la pile, les éléments sont traités de haut en bas.
La Base : c’est le cas pour lequel le problème se resoud immediatement, par exemple :
if N==0 :
return 0
dans le script ajoute2: le problème se resoud immediatement pour N == 0).
L’Hérédité : calcul à partir de paramètres plus “petits” : return 2 + ajoute2(N-1).
Une définition plus générale serait que, pour l’hérédité, il y a un appel recursif avec un argument qui se rapproche plus de la condition de base. (pour la terminaison).
def fonction_recursive(param):
if <cas de base> :
return value
else:
# instructions
fonction_recursive(f(param))
Remarque: Une instruction conditionnelle est incluse dans le corps de la fonction pour forcer la fonction à retournersans que l’appel de récurence soit exécuté (La Base). Sans cela, le programme pourrait tourner en boucle…
Comparatif itératif - récursif
Une grande partie des problèmes peut se résoudre avec une implémentation récursive, comme avec une implémentation itérative. L’une ou l’autre peut paraître plus ou moins naturelle suivant le problème, ou suivant les habitudes du programmeur.
Itératif
Récursif
Principe
Permet d’executer plusieurs fois l’ensemble des instructions
La fonction s’appelle elle-même
Format
L’itération comprend l’initialisation, la condition, l’exécution de l’instruction dans une boucle et la mise à jour (incrémenter et décrémenter) la variable de contrôle.
Seule la condition de terminaison est spécifiée.
Terminaison
L’instruction d’itération est exécutée plusieurs fois jusqu’à ce qu’une certaine condition soit atteinte.
Si la fonction ne converge pas vers une condition appelée (cas de base), elle conduit à une récursion infinie.
Taille du script
L’itération rend le script plus long
Taille du script réduite
Enfin, l’algorithme récursif utilise une pile d’appels, comme vu sur l’animation suivante:
animation issue de l'application pythontutor
Il est facile de traiter des suites avec la méthode récursive:
On pourrait représenter la pile d’execution de cette fonction de la manière suivante :
Appel à fact_recur(4)
| 4*fact_recur(3) = ?
| Appel à fact_recur(3)
| | 3*fact_recur(2) = ?
| | Appel à fact_recur(2)
| | | 2*fact_recur(1) = ?
| | | Appel à fact_recur(1)
| | | | 1*fact_recur(0) = ?
| | | | Appel à fact_recur(0)
| | | | Retour de la valeur 1
| | | | 1*1
| | | Retour de la valeur 1
| | | 2*1
| | Retour de la valeur 2
| | 3*2
| Retour de la valeur 6
| 4*6
Retour de la valeur 24
Dans le cas d’un algo recursif, pas de convergent ni d’invariant de boucle. On prouve par recurrence sur n.
a. Teminaison: si n=0, fact(0) fait un test et renvoie 1, sans appel recursif.
Hypothèse de récurrence: fact(n) termine après n appels recursifs. Montrons que fact(n+1) termine après (n+1) appels recursifs:
fact(n+1) fait un test n+1>0 donc on passe au else puis on appelle fact(n) par recurrence qui termine apres n appels recursifs. Finallement fact(n+1) termine après (n+1) appels recursifs.
b. correction: par recurrence fact(n) = n ! :
pour n = 0 : fact(n) = fact(0) = 1 = 0! (OK)
si vrai pour n, alors $fact(n+1) = (n+1)*fact(n)$ et par hyp H.R., $fact(n) = n!$ donc $(n+1)*n! = (n+1)!$ (OK)
Complexité
Calcul de la complexité : Soit T(n) le nombre d’opérations fondamentales. Pour une fonction récurrente, c’est le nombre de résolution de la fonction de récurence.
On a T(n) = T(n-1) + 1 donc T(n) = n
Analyser un algorithme récursif
Preuve de correction d’un algorithme récursif
Alan Turing (1912 – 1954) énonce ainsi son principe d’indéciablité de la terminaison d’un algorithme(1936): L’indecidabilite c’est l’impossibilité absolue et définitivement démontrée de résoudre par un procédé général de calcul un problème donné.
La terminaison, ainsi que la correction ou la complexité doivent être prouvées par des arguments mathématiques.
terminaison : recherche du convergent
correction / validité : recherche de l’invariant de boucle pour démontrer sa (non) variation selon un argument de recurence
puis finir en montrant que l’invariant de boucle ou bien le resultat obtenu repond bien à la specification de l’algorithme
Complexité d’un algorithme recursif
Pour un algorithme récursif, on compte le nombre d’appel récursif et il suffit en général de se ramener à une relation définissant une suite récurente. On se ramène souvent à évaluer une relation du type :
$$T_n = a \times T_{f(n)} + T$$
où :
$T_n$ est la complexité pour une donnée de taille n ; a est le nombre d’appel récursif ;
f(n) décrit la variation de n dans l’appel récursif;
T est la complexité des calculs hors appel récursif.
T(n) = T(0) + a×n×(n+1)/2 + n×b (suite arithmetique pour le 2e terme)
$O(n^2)$
T(n) = T(n/2) + b
$T(n) = T(1) + b×log_2 (n)$
$O(log_2 n)$
Application 1: suite de Fibonacci
La suite de Fibonacci est une suite récurente d’ordre 2: On calcule l’un de ses termes à l’aide des deux termes précédents.
Définitions
Fibonacci était le surnom de Léonard de Pise (1170 -1250) . Il a posé un problème dans lequel il cherche à calculer le nombre de couples de lapins au bout de n années, lorsqu’ils se reproduisent selon les règles suivantes :
Lors de la première année, l’éleveur démarre avec un couple de lapins nouveaux nés.
Un couple de lapins donne naissance à un nouveau couple tous les ans, à partir de la 2ème année (la 1ère année, il est trop jeune).
On peut compléter le tableau suivant présentant l’effectif de ces couples de lapins :
numero de l’année
nombre de couples de l’année précédente
nouveau nombre de couples
0
0
0
1
0
1
2
1
1 + 0 = 1
3
1
1 + 1 = 2
4
2
2 + 1 = 3
5
3
3 + 2 = 5
6
…
…
On définit la suite ($f_n$) des nombres de Fibonacci par :
Les nombres de Fibonacci apparaissent aussi dans la croissance des plantes. Le nombre de pétales des différentes fleurs est souvent un nombre de la suite de Fibonacci. On remarque que l’ angle entre deux primordia successifs, tend vers L’ANGLE D’OR, et que plus les nombres successifs sont grands, plus le rapport s’approche du NOMBRE D’OR.
Algorithme itératif
deffibonacci(n):"""
fonction qui prend en paramètre n, entier sup ou egal à O.
cette fonction utilise une variable f de type tableau.
A la fin, cette fonction retourne f[n], le terme de rang n du
tableau f qui contient les éléments entiers calculés selon l'algorithme
de fibonacci où l'élement de rang i est la somme des elements i-1 et i-2.
"""f=[]f.append(0)f.append(1)ifn<2:returnf[n]foriinrange(2,n+1):f.append(f[i-1]+f[i-2])returnf[n]
Exercice : Ecrire un programme qui permet d’afficher tous les nombres de la suite de Fibonacci, du rang 0 au rang n=10.
Parfois, l’algorithme récursif n’est pas le plus performant: Pour l’exemple de la suite de Fibonacci, on constate que les mêmes calculs sont répétés plusieurs fois, comme fibo(2) dans le cas présent pour N = 4):
pile d'appels pour la suite de fibonacci recursive
Application 2: recherche du PGCD
La méthode de recherche du PGCD utilise aussi une suite récurente d’ordre 2: On calcule l’un de ses termes à l’aide des deux termes précédents.
Problème
Etant donné deux entiers naturels n et m, calculer leur pgcd (plus grand commun diviseur)
algorithme d’Euclide
Euclide propose l’algorithme suivant:
Calculez le reste r dans la division de a par b
Si r est nul alors le pgcd est b
Sinon recommencer l’étape 1 avec a = b et b = r
Exemple d’exécution : a = 32, b = 12 :
– 32 = (2 x 12) + 8
– 12 = (1 x 8) + 4
– 8 = (2 x 4) + 0
On a donc pgcd(32, 12) = 4
La page dédiée sur wikipedia propose une illustration géométrique de cette méthode. Un couple d’entiers est vu comme un rectangle, dont le PGCD est la longueur du côté du plus grand carré permettant de carreler entièrement ce rectangle:
Explication géométrique de l'algorithme d'Euclide sur les entiers 21 et 15. - source wikipedia
Algorithme PGCD itératif
defeuclide(a,b):"""
a et b sont des entiers, a > b
euclide retourne un entier qui est le PGCD de a et b
"""r=a%bwhiler>0:a=bb=rr=a%breturnb
Preuve de l’algorithme itératif
a. Terminaison : on utilise une boucle non bornée avec y qui est le convergent. On affecte à y le reste de la division par y (c’est donc inferieur à y). y décroit ainsi jusqu’à 0, ce qui est la condition de fin de la boucle.
b. Correction : Tout diviseur commun de a et b divise aussi r = a - bq, et réciproquement tout diviseur commun de b et r divise aussi a = bq + r. Donc le calcul du PGCD de a et b se ramène à celui du PGCD de b et r.
l’invariant de boucle, c’est donc : euclide(a,b) = euclide(b, a modulo b)
C’est ce qui est réalisé par la fonction, puisque l’on a comme valeurs pour les couples (x,y) successivement :
(a,b)
(b, a mod b)
(a mod b, (a mod b) mod (a mod b))...
(* , 0)
algorithme recursif
Le PGCD d’Euclide calcule une suite définie par une récurence à 2 termes:
$r_0 = a$
$r_1 = b$
$r_2 = r_0 \\% ~r_1$
$r_{n+1} = r_{n-1} \\% r_n$
defPGCD(a,b):"""
PGCD : entier correspondant au plus grand diviseur commun de a par b
a et b : entiers tels que a > b
"""ifb==0:returnaelse:r=a%breturnPGCD(b,r)
La récursivité intervient aussi dans de nombreux problèmes où elle s’impose comme la méthode la plus adaptée, pour ne pas dire la seule. Un exemple historique est celui des tours de Hanoi. Un jeu inventé par Edouard Lucas, vers 1880. Son traitement sur ordinateur a fait sensation, grâce à la simplicité de son script récursif…
Exercices
Ex 1 :
On place un capital exprimé en euros égal à $w_0 = 1500$ avec un taux d’intérêt égal à 4,5% par an et on note $w_n$ le capital obtenu au bout de n années.
Exprimer $w_n$ en fonction de $w_{n-1}$.
Ecrire le script récursif d’une fonction capital qui calcule le montant du capital à l’année n. Cette fonction aura pour paramètres n et t, le taux d’interêt.
Calculer grâce à cette fonction la valeur du capital au bout de 10 ans.
Au bout de combien d’années le capital initial aura-t-il doublé ?
Ecrire en python le script de la fonction recursive correspondante, qui calcule au rang n le nombre $u_n$. Appeler cette fonction f.
Application géométrique
On considère un carré de côté 1. On le partage en 9 carrés égaux, et on colorie le carré central. Puis, pour chaque carré non-colorié, on réitère le procédé. On note $u_n$ l’aire coloriée après l’étape n. La suite $u_n$ est $u_{n+1} = \tfrac{8u_n}{9} + \tfrac{1}{9}$
La fonction suivante calcule la longueur d’une chaine de caractères seq passée en argument.
deflen_iterative(seq):"""
Return the length of a list (iterative)
"""count=0foreltinseq:count=count+1returncount
Réaliser la preuve de cet algorithme.
algorithme récursif
a. Montrer que la relation de récurence $u_{n+1} = 1 + u_n$ permet de compter de 1 en 1.
b. Soit la chaine de caractères s = "abcd". On veut supprimer le premier caractère de s à l’aide d’un slice python. Quelle est l’instruction python correspondante?
c. Ecrire le script python de l’algorithme récursif
Aide pour l’écriture de l’algorithme recursif : la fonction récursive s’appelera len_recursive, et aura pour argument seq. Si on veut passer en argument la liste seq de laquelle on retire le premier élément, on fait : len_recursive(seq[1:]). Il faudra alors s’inspirer de la relation de récurence suivante lors de l’appel recursif:
$$u_{n+1} = 1 + u_n$$
Ex 4 : Exponentiation
Etudions l’exponentiation à travers deux exemples.
defexp1(n,x):"""
programme qui donne x^n en sortie sans utiliser **
n : entier
x : reel
exp1 : reel
"""acc=1foriinrange(1,n+1):acc*=xreturnaccdefexp2(n,x):"""
n : entier
x : reel
exp2 : reel
"""ifn==0:return1else:returnexp2(n-1,x)*x
Combien de produits sont necessaires pour calculer une puissance n-ième avec la fonction exp1 ?
Pour la fonction exp2 : Soit $u_n$ le nombre de produits nécessaires pour calculer une puissance n-ième. Quelle est la relation de récurrence vérifiée par $u_{n+1}$ ?
$$u_{n+1} = u_n + ...$$
En déduire la complexité pour chacune de ces 2 fonctions.
Ex 5: dichotomie recursif
la méthode de dichotomie pour calculer la racine d’une fonction. Soit une fonction f : R → R continue, dont on sait qu’elle a une racine et une seule sur un intervalle [a, b]. On cherche une valeur approchée de cette racine. voir figure ci-dessous
principe de la dichotomie
Soit c = (a + b)/2, qui divise l’intervalle initial en deux parties égales. On calcule f(c) et on compare son signe à f(a) et f(b). La racine est nécessairement dans le sous-intervalle aux bornes duquel la fonction f prend deux valeurs de signes opposés (ou éventuellement nulles toutes les deux). On est donc conduit à répéter la recherche sur l’intervalle [a, c], qui est similaire au premier, d’où le caractère récursif de cet algorithme. La récursion doit être stoppée lorsque la valeur |f (c)| est inférieure à une tolérance ε que l’on fixe en fonction de la précision souhaitée.
On utilise la fonction dichotomie_recursive pour la fonction f(x):
deff(x):returnx**2-2.0
On fait alors:
>dichotomie_recursive(f,0.0,2.0,1e-3))1.4140625
Interpreter le résultat obtenu.
Que valent chacun des paramètres de la fonction lors du premier appel avec dichotomie_recursive(f,0.0,2.0,1e-3)) ?
Que valent chacun des paramètres lors du premier appel recursif par cette fonction?
A quel moment cette fonction va-t-elle finir?
Prouver la terminaison de cette fonction.
Soit un tableau contenant des nombres entiers triés par ordre croissant :
import numpy.random
import numpy
N = 50
L = numpy.random.randint(0,200,N)
L = numpy.sort(L)
Écrire une fonction qui permet d’insérer un nombre entier x dans cette liste. La recherche de l’emplacement d’insertion doit se faire par dichotomie. Pour faire l’insertion juste avant l’élément d’indice i :
L1 = numpy.insert(L,i,x)
Cela renvoie un nouveau tableau avec l’élément inséré.
Une planche, malgré la diversité, est toujours constituée:
d’un deck (court, long)
d’un tail (plat, relevé)
de trucks (hauts, bas)
de roues (à gommes tendres, dures)
d’une décoration (image sous le deck)
C’est son état.
Cette planche peut repondre egalement à un ensemble de messages, qui forment ce que l’on appelle l’interface de l’objet. C’est au travers de ces méthodes que l’on peut interagir avec l’objet, ou que les objets peuvent interagir entre eux.
On peut lui associer une méthode skateboard_pour_parc qui renvoie True si la planche est de type street ou False si la planche est de type cruising, ou prevue pour la decoration.
Un objet comprend donc :
une partie figée qui représente son état, et qui est constituée de champs ou attributs.
une partie dynamique qui décrit son comportement, à l’aide de déclarations de méthodes, qui doivent répondre à des messages.
Classe et instance de classe
La structure interne des objets et les messages auxquels ils repondent sont définis dans une classe. Une classe décrit les méthodes de création d’objets de ce type (on parle d’instance de classe), et les méthodes auxquelles répondront les objets de ce type dans la reception des messages.
Avec l’exemple précédent, la classe Skateboard pourrait contenir:
les méthodes de création des instances des différents skateboards. On y définit les attributs pour chaque nouvelle planche de skateboard que l’on créé. Chaque planche de skate constitue une instance de classe.
les méthodes de la classe skateboard, qui repondent aux messages du genre: skateboard_pour_parc? Un message est constitué du nom de la méthode, et permet d’interagir avec celui-ci. Ces méthodes sont accessibles à tous les skates qui sont des instances de la classe skateboard.
En python, la création d’une classe commence par le mot clé class suivi du nom de la classe, de deux points et d’une indentation.
classSkateboard:
Toute la partie indentée contient les méthodes de création des instances de cette classe et les méthodes de cette classe.
Lors de la programmation, on devra faire référence à l’instance de l’objet sur lequel on travaille: le mot clé self permet ceci en python.
La méthode de création d’un objet est définie par def __init__ suivi au minimum de l’argument self, et eventuellement d’autres arguments.
Les attributs des objets de cette classe sont définis dans cette méthode. Ils sont codés sous la forme self.attribut, et peuvent faire référence aux arguments passés lors de l’instanciation.
Enfin, chaque méthode de classe est définie à l’aide de: def nom_de_la_methode. Celle-ci prend aussi au minimum, l’argument self.
On instancie alors un premier skateboard de la manière suivante:
>>>mon_premier_skate=Skateboard()
Le programme interprete alors l’instruction: Skateboard.__init__(mon_premier_skate), c’est à dire qu’il execute la méthode de classe Skateboard.__init__, avec le paramètre self=mon_premier_skate.
un premier skateboard bien classique
Et on envoie le message suivant:
>>>mon_premier_skate.skateboard_pour_parc()True
Le programme interprete alors l’instruction: Skateboard.skateboard_pour_parc(mon_premier_skate),
Ce n’est pas très explicite pour un humain. On préfèrera souvent choisir un descriptif personnalisé. Nous allons programmer la chaine de caractères qui sera renvoyée lors du print.
On ajoute maintenant à la classe Skateboard la méthode __repr__() qui sera appelée lorsque l’on utilise print(objet):
classSkateboard:def__init__(......def__repr__(self):ifself.skateboard_pour_parc():return"skateboard de type {} qui permet de rider en parc".format(self.deck)else:return"skateboard de type {} qui ne permet pas de rider en parc".format(self.deck)
On construit à nouveau l’instance de classe mon_sector_9, et on fait print(mon_sector_9):
Remarquer que l’appel à la méthode skateboard_pour_parc se fait en identifiant l’objet qui possède cette méthode: self.skateboard_pour_parc(). Et ici, on n’ajoutera pas de nouvel argument. (On ne met pas self en argument lors du message envoyé à cet objet).
Surcharge d’une fonction de la librairie standard: Ce que l’on vient de réaliser est une surcharge de la fonction print de la librairie standard.
Mais il existe d’autres méthodes de surcharge, prévues pour les opérateurs, ainsi que pour certaines fonctions. On pourra se référer au lien suivant pour approfondir le sujet.
Encapsulation: getter et setter
Lire un attribut: accesseur ou getter
L’utilisateur du programme ne devrait pas utiliser la méthode pointée précédente nom_objet.nom_attribut, permettant d’accéder aux valeurs des attributs: on ne veut pas forcement que l’utilisateur ait accès à la représentation interne des classes.
Pour utiliser ou modifier les attributs, on utilisera de préférence des méthodes dédiées dont le rôle est de faire l’interface entre l’utilisateur de l’objet et la représentation interne de l’objet (ses attributs).
Les attributs sont alors en quelque sorte encapsulés dans l’objet, c’est à dire non accessibles directement. la liste des méthodes devient une sorte de mode d’emploi de la classe.
Pour obtenir la valeur d’un attribut nous utiliserons la méthode des accesseurs (ou “getters”) dont le nom est généralement : getNom_attribut().
En console, une fois l’instance de classe mon_sector_9 définie, on fait:
>>>mon_sector_9.getTail()`long`
Modifier des attributs : les mutateurs ou setters
De la même manière, pour modifier la valeur d’un attribut, on devrait utiliser une méthode dédiée. Le nom de cette méthode commence en principe par set:
Chaque classe définit ses propres manières de stocker, d’acceder et de manipuler les données. C’est le Docstring qui permettra de prendre connaissance des détails, comme par exemple celui de la classe Sept_Familles:
classSept_Familles:"""
NAME
Sept_Familles
DESCRIPTION
constructeur pour les cartes du jeu
PARAMETERS
famille (str): nom de la famille
qui(str): membre de la famille
choix parmi ('Grand-père','Grand-mère','Pére','Mère','Fils','Fille')
FUNCTIONS
get_Attributs
"""
On peut alors prendre connaissance du docstring en faisant:
>>> help(Sept_Familles)
Interface
L’interface d’une classe est représentée par le diagramme suivant:
Une représentation d'une classe
La suite en TP
TP Jeu des 7 familles: Lien(Sans interface graphique)
Cours sur les Files et autres structures linéaires: Lien
Types abstraits
La résolution d’un problème par un programme nécessite:
de définir les données du problème
d’utiliser des instructions du langage sur ces données
Souvent, la résolution du problème demande d’arranger ces données dans un type abstrait, afin d’avoir une résolution plus efficace.
Un type abstrait est défini par son interface, qui est indépendante de son implémentation.
Les types abstraits sont des types structurés. On a déjà vu des types structurés natifs: les types séquences de texte (string), les types séquentiels (listes, tuples), et les mappages (dictionnaires).
Un type abstrait est caractérisé par une interface de programmation qui permet de manipuler les données de ce type. Sans pour autant avoir connaissance du contenu des fonctions proposées par l’interface.
Spécifier un type abstrait, c’est définir son interface, sans prejuger de la façon dont ses opérations sont implémentées.
Implémenter, c’est fournir le code de ces opérations. Plusieurs implémentations peuvent correspondre à la même spécification. On verra dans ce chapitre la programmation dans un style fonctionnel. Il viendra plus tard la programmation par objet.
On verra dans un premier temps, deux exemples de types abstraits: Les listes chainées et les tableaux. Dans un chapitre ultérieur, nous verrons les types abstraits Piles, Files, et Graphes.
Listes chaînées
Une liste chaînée est une séquence ordonnée d’éléments.
L’avantage sur un tableau (la Liste native en Python), c’est qu’en parcourant la Liste chainée, quelle que soit la profondeur de parcours, celle-ci présente la même structure.
On peut donc lui associer des méthodes ou fonctions, qui seront indépendantes de cette profondeur. Que l’on pourra utiliser de la même manière à chaque niveau de la liste chainée.
classes à parcourir après le collège
classes à parcourir après la 2nde
La liste L précédente représente la chaine: "2nde" -> "1ere" -> "Term" -> "Univ
L = ("Univ",("Term",("1ere",("2nde", ()))))
La liste chainée L contient 2 éléments (tete, queue) et queue est elle-même une liste chainée, contenant aussi (tete, queue). Le dernier élément: (tete, ()).
On utilisera par exemple une liste chainée lorsqu’il y a une filiation entre les éléments, et surtout, lorsque l’on doit souvent INSERER ou SUPPRIMER des éléments qui ne sont pas forcement à la fin de la liste.
L’interface d’une liste chainée
L’interface fournit certaines fonctions.
fonctions qui implémentent la liste chainée L
nom
créer une liste vide
creer_liste()
questionner si la liste est vide
liste_vide(L)
insérer un élément e en tête de liste et retourne une nouvelle liste
inserer_tete(L,e)
retourne l’élément de tête (premier élément)
tete(L)
retourne la liste privée de son premier élément (retourne donc le 2e élément)
queue(L)
insere un nouvel element_a_inserer juste avant l’élement recherché dans la liste
insere(L,element_recherche,element_a_inserer)
retourne une liste python avec tous les éléments de la liste chainée
elements_liste(L)
Le contenu de ces fonctions va dépendre de l’implémentation choisie par le programmeur.
Par exemple, si l’on choisit d’implémenter la liste chainée par un tuple, on aura pour la premiere fonction:
defcreer_liste():return()
Alors que si l’on choisit plutôt une liste:
defcreer_liste():return[]
Généralités sur les listes chainées
Une liste chainée est un objet:
non mutable:
on peut la modifier en partie (ajout/suppression d’un élément), mais sa copie se fait par valeur.
dynamique:
on peut modifier sa taille après création, par exemple en faisant: L = inserer(L, e), mais cela va créer un nouvel objet.
les éléments ont une relation d’ordre entre eux.
on peut atteindre un élément au rang i en temps proportionnel à i, avec une boucle par exemple.
Mémoire: Contrairement aux tableaux, les éléments d’une liste chaînée ne sont pas placés côte à côte dans la mémoire. Chaque case pointe vers une autre case en mémoire, qui n’est pas nécessairement stockée juste à côté.
L’interface d’une liste chainée doit aussi proposer l’insertion d’un élément au rang i, en temps constant. (Intercaler cet élément entre 2 éléments de la liste). Ceci ne peut pas être réalisé avec l’implémentation vue plus haut.
Nous verrons d’autres implémentations pour ce type abstrait.
Attention: les listes chaînées et les Listes Python sont différentes, il ne s’agit pas des mêmes objets.
Tableaux, choix d’une structure de données native en python
Les tableaux statiques sont des structures de données de taille fixe, où chaque donnée est du même type. C’est comme ceci que sont représentées les collections dans des langages comme C, Java, Ocaml, …
La taille du tableau est fixe à sa création : on ne peut pas l’agrandir ou le réduire sans en recréer un nouveau.
Un tableau peut être représenté en Python à l’aide d’une liste (type list), un tuple (type tuple), ou bien une matrice numpy (numpy.array).
List python
Les tableaux en python sont implémentés par le type list, qui est en réalité un tableau dynamique: leur taille est variable, et les éléments stockés peuvent être de types différents (idem pour Javascript). Pour utiliser le type list en tant que tableau statique, on s’interdira les aspects dynamiques.
Création
On rappelle que, pour créer une liste python, on peut utiliser les techniques suivantes:
création par extension: en listant les éléments du tableau: T = [1,2,3]
par concaténation: On peut utiliser une somme d’éléments à l’aide des opérateurs + et *, par exemple: T = [0] * 100
par compréhension: on s’appuie sur un itérateur (fonction génératrice), exemple: T = [i for i in range(ord('A'), ord('Z')+1], ou T = [x**2 for x in range(1,11)]
par ajout dans une table vide (append)
à l’aide de la fonction list: codes = list(range(ord('A'), ord('Z')+1), T = list('bonjour')
Manipuler
On accède à un élément d’un tableau à l’aide d’un indice, qui peut être positif: T[1] est le deuxière élément par exemple, T[0] étant le premier. Ou bien à l’aide d’un entier négatif, ce qui fait que T[len(T)-1] est le même que T[-1]
Parcourir
Le plus simple est de parcourir directement par élément
foreleminL:print(elem)
parcourir par indice:
Très utile si on veut modifier les valeurs lors du parcours:
foriinrange(len(T)):T[i]+=1
ou bien lorsque l’on veut parcourir 2 tableaux à la fois:
Pour des tableaux à plusieurs dimensions: On peut accéder aux éléments d’un array A en utilisant la syntaxe A[i, j] , où i et j sont respectivement le numéro de ligne et le numéro de colonne de l’élément au sein du tableau. L’opérateur : permet de sélectionner plusieurs éléments, voire tout une ligne ou colonne.
Tuple
Pour un tuple, celui-ci contiendra 2 données:
la liste des valeurs, de dimension fixe. On mettra None pour les valeurs non renseignés.
la valeur de la taille de la liste.
Par exemple:
T=([6,7,8,None,None],5)
C’est alors un objet qui est:
statique: sa taille ne varie pas une fois celui-ci créé
non mutable: mais avec un élément qui lui, peut être mutable:
On ne peut pas modifier T[0] ou T[1]. Ce sont les éléments d’un tuple.
Mais on peut modifier en partie T[0], par exemple avec une instruction du genre: T[0][i] = x. La copie de T[0] se fait par reference.
Un tableau peut servir à implémenter une grille de notes par exemple:
Tableau de notes
Supposons, pour simplifier, que le tableau ne contient que les notes de Kyle:
Tableau des notes de Kyle
On peut représenter cet ensemble de notes par le tableau:
T=([6,7,8,None,None],5)
Petits rappels sur le tuples:
Construction par extension:
fruits=('pommes','oranges')
Construction par concaténation:
t=()t=t+(1,)# ne pas oublier , sinon cela génère une listt=t+(2,)print(t)(1,2)
Construction par compréhension:
carres=tuple(x**2forxinrange(1,11))# ne pas oublier de mettre tuple au debut
Alors, pour accéder à l’un des éléments, on fait: tableau[ligne i][colonne j]:
List et tuple
>>>tableau[0][1]# correspond à la 2e (j=1) note de hugo (i=0)1400
Array
>>>tab1=np.array([[1,2],[3,4],[5,6]])# tab1 est un array de 3 lignes et 2 colonnes>>>tab2=np.array([[1,2,3],[4,5,6]])# tab2 est un array de 2 lignes et 3 colonnes>>>np.ones((3,5))# un tableau de 3x5 rempli de 1>>>np.zeros((4,4))# un tableau de 4 lignes et de 4 colonnes contenant que des 0
Tableaux dynamiques et tableaux statiques
Les tableaux vus ci-dessus sont des tableaux statiques: leur taille ne peut pas être modifiée. Dans le cas où l’on ait besoin d’agrandir le tableau, il faut le copier dans un nouveau tableau, plus grand.
Python implémente naturellement un autre type de tableau, que l’on appelera dynamique: Les Listes Python. Ce problème de dimension n’apparait pas dans les Listes Python, qui apportent de surcroit des méthodes bien pratiques comme append et pop.
Exercices sur les listes
On propose l’implémentation suivante pour les listes chainées:
defcreer_liste():"""exemple:
L = creer_liste()
"""return()defliste_vide(L):"""exemple:
liste_vide(L)
"""returnL==()definserer_tete(L,e):"""exemple:
L = inserer_tete(L,e)
"""return(e,L)deftete(L):"""exemple:
L = (1,(2,()))
tete(L) -> 1
"""returnL[0]defqueue(L):"""exemple:
L = (1,(2,()))
queue(L) -> (2,())
"""returnL[-1]definserer(L,element_recherche,element_a_inserer):"""exemple:
L = (1,(2,()))
inserer(L,2,3) -> (1,(3,(2,())))
"""Liste_des_elements=[]# recherchewhileelement_recherche!=tete(L):Liste_des_elements.append(tete(L))L=queue(L)# insertionL=inserer_tete(L,element_a_inserer)foriinrange(len(Liste_des_elements)-1,-1,-1):L=inserer_tete(L,Liste_des_elements[i])returnLdefelements_liste(L):Liste_des_elements=[]whilenotliste_vide(L):element=tete(L)L=queue(L)Liste_des_elements.append(element)returnListe_des_elements
Exercice 1: parcours scolaire
Le parcours scolaire est un type abstrait qui s’apparente à une Liste. Les éléments sont disposés dans cette Liste sous la forme:
('Terminale', ('Premiere', ('Seconde', ())))
L’interface propose les fonctions suivantes:
creer_liste, liste_vide, inserer, tete, queue.
1. Quelles instructions, utilisant l’interface, vont créer la Liste parcours_lycee de la manière suivante: ('Terminale', ('Premiere', ('Seconde', ())))?
2. Quelle instruction va permettre de connaitre la dernière classe visitée lors du parcours scolaire?
5. On souhaite utiliser ce type abstrait pour décrire le parcours universitaire. Quelle serie d’instructions va créer la structure de données du parcours qui ira de Licence 1 à Master 2? Cette liste s’appelera parcours_univ
6. On souhaite maintenant créer une liste unique appelée scolarite, issue de la jonction des deux listes, parcours_lycee et parcours_univ. Ecrire le script correspondant.
Exercice 2: composition d’un train
On cherche à implémenter la construction d’un train pour voyageurs, motrice et wagons, à l’aide d’une liste chainée.
Le train suit l’ordre suivant:
motrice
wagon_1
wagon_2
wagon_3
1. Qu’est ce qui est affiché par le programme suivant?
2. Quelle instruction de l’interface de liste faut-il utiliser pour consulter la nature du dernier wagon du train?
3. La fonction elements_liste va retourner les éléments de la liste chainée, en une liste python. Quelle instruction, utilisant elements_liste, va retourner la liste ['wagon_3', 'wagon_2', 'wagon_1','motrice']?
4. INSERTION: On souhaite modifier la liste L1 et intercaler wagon_bar entre le wagon_1 et le wagon_2.
Quelle instruction utilisant la fonction insere de l’interface de liste va modifier L1 de cette façon?
Quelle sera l’objet retourné?
Repérer les différentes parties de cette fonction.
5. Supprimer le wagon de queue à l’aide d’une instruction de l’interface.
Exercice 3: separation d’une liste
1. Compléter la fonction separe qui sépare les éléments d’une liste en deux listes selon s’ils sont inférieurs (strictement) ou supérieurs (et égal) à une valeur v:
defsepare(L,v):L_inf=creer_liste()L_sup=creer_liste()whilenotliste_vide(L):# à completer# utilise les fonctions tete, queue et insere_tete# # returnL_inf,L_sup
2. Compléter alors le programme au niveau du repère ICI. Le programme affiche les 2 listes une fois celles-ci séparées. La liste L contiendra les valeurs à séparer.
L=creer_liste()forelemin[1,3,20,18,16,11,101,12,15,2,5,4,2,8,1]:L=inserer_tete(L,elem)v=12# ICI, appel de la fonction separeL_inf,L_sup=separe(L,v)print(L_inf)print(L_sup)# (1, (3, (11, (2, (5, (4, (2, (8, (1, ())))))))))# (20, (18, (16, (101, (12, (15, ()))))))
Exercices sur les Tableaux statiques
On propose l’implémentation suivante pour les tableaux statiques:
T=(['lundi','mardi','mercredi','jeudi','vendredi'],5)deftaille(T):"""exemple:
> taille(T)
> 5
"""returnT[1]defelement(T,i):"""exemple:
> element(T,3)
> 'jeudi'
"""returnT[0][i]defremplacer(T,i,e):"""exemple:
> remplacer(T,2,'jour des enfants')
> T
> (['lundi','mardi','jour des enfants','jeudi','vendredi'],5)
"""# à completer
Exercice 1: Utiliser l’interface du tableau
Tableau de notes
1. Soit le tableau qui implémente les notes de Kyle dans les matières C1, C2, C3:
T=([6,7,8],3)
a. Ecrire l’instruction qui retourne la note de Kyle dans la matière C3.
b. Kyle n’a pas eu 8, mais 12/20 dans la matière C3. Ecrire l’instruction qui modifie sa note 8 en 12, à partir d’une fonction de l’interface des tableaux.
c. Compléter le script donné plus haut pour cette fonction.
d. Ecrire le script d’une fonction moyenne qui calcule la moyenne des notes du tableau T.
2. Soit le tableau suivant qui implémente les notes de Kyle, Sean, Quentin et Zinedine dans les matières C1, C2, C3:
a. Recopier le tableau T et remplacer les ‘?’ par les bonnes valeurs (utiliser l’image plus haut). Que signifie le tuple (4,3) placé comme 2e élément du tableau?
b. Utiliser l’instruction taille de l’interface pour donner le nombre d’élèves dans le tableau. Puis le nombre de colonnes (matières):
n_eleves=taille(...)n_matieres=taille(...)
2c. Modifier la fonction remplacer pour que celle-ci modifie la note dans la matière voulue pour un élève donné.
Par exemple: Pour modifier la note de la colonne 2 de l’élève au rang 0 (premiere ligne):
Si on veut lui mettre 12, on fera: remplacer(T,0,2,12)
Definition: Une structure de données est une manière de stocker, d’accéder à, et de manipuler des données (comme les types list ou dict de Python).
Definition: Un type abstrait décrit essentiellement une interface, indépendamment du langage de programmation.
Un premier exemple
La pile est une manière de ranger les données.
Elle correspond exactement à l’image traditionnelle d’une pile de cartes ou d’assiettes posée sur une table. En particulier, on ne peut accéder qu’au dernier élément ajouté, qu’on appelle le sommet de la pile.
L’illustration suivante montre que c’est la structure de données à adopter si l’on veut sortir d’un labyrinthe…
parcours pour sortir d'un labyrinthe
Le labyrinthe peut être modélisé par les coordonnées de ses noeuds, ainsi qu’une liste de directions possibles (ouvertures) pour chacun de ses noeuds :
modelisation d'un labyrinthe
En observant l’animation de la tortue dans le labyrinthe, on peut supposer que la pile des sommets visités (les cases du labyrinthe) sont, dans l’ordre :
(4,0), (3,0), (3,1), (3,2), (4,2), (4,1) …
puis le chemin inverse jusqu’au sommet (3,0) :
(4,2), (3,2), (3,1), (3,0), …
Une fois revenu au sommet (3,0), on reprend l’exploration vers (2,0), (2,1),…
La tortue suit son chemin jusqu’à arriver à une impasse (ou un sommet déjà visité). Alors, elle doit être capable de revenir sur ses traces. C’est pour cela qu’elle mémorise son parcours dans une pile, qu’elle pourra remonter (c’est à dire dépiler) au besoin. Cette pile de sommets visités correspond au fil d’Ariane, rendu célèbre par la mythologie (Thésée et le Minautore).
Lorsqu’elle s’avance plus en profondeur dans le labyrinthe, vers des sommets encore non explorés, elle empile.
Lorsqu’elle revient sur ses traces, elle dépile (elle retire des sommets de la pile).
pile de sommets du labyrinthe
Lorsque la tortue arrive à la case (4,1), l’impasse, la pile a alors la configuration pile a (voir schéma plus bas).
Elle revient jusqu’à (3,0).
Après avoir dépilé (4,1),(4,2),(3,2),(3,1), la pile est alors la pile b.
Puis, lorsqu’elle est parvenu à une bifurcation vers une nouvelle direction, elle poursuit son exploration (et empile à nouveau) : pile c. Qu’il faudra encore prolonger pour atteindre la sortie (en bas à droite).
pile du parcours en profondeur
Deuxieme exemple : une expression correctement parenthésée
Principe : On lit l’expression de gauche à droite et on empile au fur et à mesure les caractères ouvrants : [, {, (. On dépile lorsqu’on lit le caractère fermant correspondant. A la fin, la pile doit être vide.
Dans l’exemple suivant, on voit que l’expression [a+(b+c)] est correctement parenthesée. Ce qui ne serait pas le cas pour [a+(b+c]).
Définitions
La pile: interface
La pile est une structure de données appropriée quand :
On veut stocker des éléments dont le nombre est variable, et inconnu à l’avance.
On peut ou on doit se contenter d’accéder au dernier élément stocké.
Dans d’autres cas, il faudra utiliser une autre structure de données, comme par exemple un tableau.
Une Pile est une structure de données linéaire (les données sont rangées sur un ligne ou une colonne). Le dernier élément entré sera aussi le premier à sortir (Last In First Out : LIFO).
Les méthodes (= fonctions) disponibles pour cette structure sont :
construction (d’une pile vide)
test d’une pile vide (renvoie True si la pile est vide)
ajout d’un élément (empiler = push), mis au sommet de la pile
retire le premier élément de la pile, celui au sommet (dépiler = pop) si la pile est non vide et renvoie cet élément.
lire le sommet de la pile
Implémenter un pile en Python en langage natif
Le type List en Python possède déjà toutes les méthodes d’une pile :
pile=[]# creation d'une pilepile==[]# tester si la pile est videpile.append(valeur)# empile valeur dans la pilepile.pop()# depiler l'element au sommetpile[-1]# lire l'element au sommet de la pile
Lorsque l’on fait référence à une structure de données de type pile en traduisant un algorithme en Python, il faudra se contenter de ces 5 instructions.
Créer une nouvelle Interface
Les types abstraits, comme les piles, sont définis par leur interface (comment on s’en sert) plutôt que par leur implémentation (comment ils fonctionnent). Ils permettent d’étudier des algorithmes indépendamment du langage utilisé.
Rappels:
L’interface de la structure de données décrit de quelle manière on peut la manipuler, par exemple en utilisant append pour le type list ou get pour le type dict.
L’implémentation de la structure de données, contient le code de ces méthodes (comment fait Python). Il n’est pas nécessaire de connaître l’implémentation pour manipuler la structure de données.
On verra ici deux manières d’implémenter la pile.
Implémentation fonctionnelle
Pour traduire un algorithme utilisant cette structure pile, il peut être préférable de définir des instructions portant les noms de ces 5 instructions:
defPile():"""creation d'une pile vide à l'aide de l'instruction :
pile = Pile()
"""return[]defest_vide(pile)# à compléterdefempile(valeur,pile):# à compléterdefdepile(pile):# à completerdefsommet(pile):# à completer
Implémentation en Programmation Objet
On peut créer un type (= une classe) Pile personnelle en Python.
Les méthodes (fonctions) déclarées précédemment sont alors associées à l’objet Pile. L’appel d’une méthode se fait à l’aide de l’instruction :
Rappel : Objet = type mutable. Quelle que soit la façon avec laquelle la pile est implémentée, il faudra se souvenir que celle-ci est un objet mutable. Cela a des conséquences sur la manière avec laquelle la pile est passée en argument d’une fonction, et comment cette fonction modifie la pile.
Pile et recursivité
Tout algorithme récursif peut être mis sous forme d’algorithme itératif avec une structure de données en pile.
Le problème est que celle-ci ne s’effectue pas en temps constant.
Implémentation avec l’extension deque
La bibliothèque standard possède toutefois un module nommé collections qui contient quelques structures de données supplémentaires, dont le type deque, qui est une implémentation de file:
Le types abstrait Liste ne concerne pas le type list en python. C’est une liste chaînée (ou liste liée): une structure de données composées d’une séquence d’éléments de liste.
Ces éléments sont aussi appelés noeuds ou maillons.
La tête d’une liste est son premier maillon. La queue d’une liste, son dernier.
Chaque maillon M contient:
une valeur, de n’importe quel type.
un lien (ou pointeur) vers le maillon suivant de la séquence.
Il s’agit d’une structure linéaire, mais dans laquelle les éléments n’occupent pas à priori, des positions contigües dans la mémoire:
illustration:
elements dans une liste
Pour relier ces éléments ensembles, dans une même structure de données, il faut alors utiliser des pointeurs.
liste chainée grâce aux pointeurs
L’élément A pointe sur B, qui pointe sur C, qui pointe sur D. D, lui, ne pointe sur … rien!
La plupart du temps, le lien du dernier maillon a pour valeur None en python, signifiant un pointeur sur rien.
Interface
On trouve en général les opérations suivantes pour l’interface d’une Liste:
est_vide : renvoie True si Liste vide
taille : renvoie le nombre de maillons de la séquence
get_dernier_maillon
get_maillon_indice
ajouter_debut
inserer_apres
ajouter_fin
supprimer_apres
…
Implémentation en POO
L’implémentation est plus naturelle en programmation orientée objet
voir le chapitre POO
Son attribut tete est de type Maillon , ou bien vaut None si la liste est vide.
Cette classe ne comporte pour l’instant que sa définition de la variable tete, mais elle est créée pour contenir, plus tard, l’implementation des différentes méthodes prévues par l’interface.
Interêt et inconvenient par rapport aux listes en python
L’interface d’une liste chainée fournit des méthodes plus efficaces que la Pile, la File ou le tableau, lorsque l’on veut par exemple: insérer, ou supprimer un élément dans la séquence.
insertion dans une liste
Cette opération est prévue par l’interface d’une liste chainée => O(n): inserer_apres(i), où i est l’indice de l’élément après lequel on veut insérer.
Avec une liste python, qui implémente la Pile (voir cours) cela necessite de décaler toutes les valeurs de rang supérieur à i . C’est une opération qui est évaluée en O($n^2$) pour sa complexité asymptotique.
Il s’agit du même problème lorsque l’on veut supprimer après i.
Un autre avantage est la possibilité de faire pointer le dernier élément sur le premier de la liste. On créé ainsi une liste périodique.
Inconvénient: Pour accéder à un maillon de rang i dans une liste chainée, il faut remonter la liste depuis le premier élément (celui de tête), jusqu’à celui de rang i. Et cela se fait avec une complexité asymtotique O(n).
4. Ajouter les lignes suivantes et dérouler le programme ligne par ligne:
s=L.tetes.val='1'print(L.tete.val)print(M1.val)
Qu’affiche la console? Ce résultat était-il prévisible? Pourquoi? (la copie s = L.tete se fait-elle par valeur ou bien par référence)
Exercice 2: afficher les éléments de liste
On cherche à parcourir les éléments d’une liste chainée L.
On propose un premier algorithme itératif. Celui-ci stocke l’élément de tête de L dans une variable M.
Puis une boucle non bornée parcourt les différents maillons de L jusqu’à ce que M.suiv soit None, marquant le maillon de queue.
On affiche alors les valeurs M.val de ces maillons avec print.
Et on passe au maillon suivant: M = M.suiv
1. Ecrire le script itératif.
2. Adapter ce script pour en faire une fonction recursive qui prend en paramètre un maillon M, et affiche toutes les valeurs jusqu’à la fin de la liste. La condition d’arrêt (Base) sera M.suiv is None.
La fonction doit renvoyer une chaine de caractères fabriquée de la manière suivante : A => ... => ... => D
Compléter après le return:
classMaillon:def__init__(self):self.val=Noneself.suiv=NoneclassListe:def__init__(self):self.tete=NoneL=Liste()M1,M2,M3=Maillon(),Maillon(),Maillon()M1.suiv=M2M2.suiv=M3M1.val='A'M2.val='C'M3.val='D'L.tete=M1defaffiche(M):ifM.suivisNone:returnstr(M.val)# affiche la valeur de queueelse:.....
3. Comment appeler cette fonction afin qu’elle affiche TOUS les éléments de la liste L, du premier (tête) au dernier? Tester avec la liste ACD décrite dans le cours.
Exercice 3: Insertion d’un élément
insertion dans une liste
Soit la liste chainée L: ‘A’ => ‘C’ => ‘D’
On souhaite maintenant modifier la séquence de L créée dans l’exercice 2. On va insérer un élément de valeur B à la $2^e$ position:
A => B => C => D
Ajouter dans votre programme les instructions qui permettront de:
1. Créer un nouveau maillon M2.
2. Affecter ‘B’ comme valeur à M2.
3. Modifier le lien M2.suiv pour que celui-ci pointe vers le 3e élément de ma_liste.
4. Modifier le lien L.tete.suiv pour recréer la liste chainée. (ou bien celui de M1, ce qui revient à la même chose).
5. Utiliser la fonction affiche pour afficher les éléments de L.
6. Que se passerait-il avec cette fonction affiche si on mettait M4.suiv = M1? (liste chainée circulaire).
Correction des exercices
Exercice 1
# correction de l'exercice 1classMaillon:def__init__(self):self.val=Noneself.suiv=NoneclassListe:def__init__(self):self.tete=Nonema_liste=Liste()M1,M2,M3=Maillon(),Maillon(),Maillon()M1.val='Premier'M2.val='Troisieme'M3.val='Quatrieme'M1.suiv=M2M2.suiv=M3M3.suiv=Nonema_liste.tete=M1print(ma_liste.tete.val)print(ma_liste.tete.suiv.val)print(ma_liste.tete.suiv.suiv.val)s=ma_liste.tetes.val='1'print(ma_liste.tete.val)print(M1.val)
Exercice 2
# Correction de l'exercice 2 en ligne question 2.1M=L.tetewhilenotM.suivisNone:print(M.val)M=M.suivprint(M.val)
Pour le script recursif:
# Correction de l'exercice 2.2 en lignedefaffiche(M):ifM.suivisNone:returnstr(M.val)else:returnstr(M.val)+'=>'+affiche(M.suiv)# Correction question 2.3 en ligne>>>print(affiche(L.tete))'A=>B=>C=>D'
Les graphes et les arbres permettent de construire des schémas qui mettent en évidence une structure sur des données.
graphe modelisant un reseau social
Complexité et morphologie d’un graphe - définitions
On appelle graphe la donnée d’un ensemble fini V de points (ou sommets du graphe, vertices en anglais) et d’un ensemble E de liens entre ces points.
$$G = (V,E)$$
L’ensemble E de liens peut être vu comme une relation R sur V × V. Il peut être représenté par une matrice d’adjacence.
Lorsque cette relation est symétrique (c’est à dire que l’existence d’un lien entre un sommet s1 et un sommet s2 est réciproque) le graphe est dit non orienté. Un lien est appelé une arête.
Lorsque cette relation n’est pas symétrique, le graphe est dit orienté. On parle alors d’arc entre deux sommets.
graphe orienté/non orienté
Un chemin C est une suite consécutive d’arêtes: C = {s0s1, s1s2, …, sk-1sk} avec C ⊂ E.
Des poids peuvent être associés aux liens d’un graphe, par exemple pour représenter la distance. Il s’agit alors d’un graphe pondéré.
Un graphe peut servir à modéliser un reseau d’ordinateurs, un reseau social, les distances entre villes par la route…
Lorsqu’un graphe non orienté est en un seul morceau, c’est à dire lorsqu’il existe pour tous sommets s1 et s2 un chemin les reliant, le graphe est dit connexe.
graphes connexe/non connexe
Des poids peuvent être associés aux liens d’un graphe, par exemple pour représenter la distance. Il s’agit alors d’un graphe pondéré.
exemple de graphe pondéré
Et lorsqu’un chemin mène d’un sommet s à lui-même, on parle de cycle.
cycle dans un graphe
Mesures sur un graphe
Ordre: le nombre de ses sommets
taille : le nombre de ses arêtes
degré d’un sommet s: nombre d’arêtes qui relient ce sommet à d’autres sommets.
Pour un graphe orienté, le degré d’un sommet est le nombre d’arcs qui sont dirigés vers ce sommet.
un graphe est dit complet si tous ses sommets sont connectés entre eux deux-à-deux. Pour N sommets, cela correspond à un nombre d’arcs égal à: (graphe non orienté)
$$\tfrac{N \times (N-1)}{2}$$
La densité D d’un graphe est une indication générale de sa connectivité et indique s’il y a beaucoup ou peu d’arêtes. C’est le rapport entre le nombre d’arêtes existantes et leur nombre possible:
$$D = \tfrac{2.A}{N \times (N-1)}$$
Le graphe est creux si sa densité est proche de zero, et dense si elle se rapproche de 1.
Diamètre d’un graphe: plus longue distance entre sommets du graphe. Voir plus loin.
Application: Choisir la structure de donnée adaptée
Question: Pour chacun des exemples suivants, choisir le type de graphe adapté parmi: graphe orienté/non orienté, pondéré, non connexe, sans cycle. Précisez également ce que représentera un sommet, et ce qui sera une arête.
un reseau de villes reliées par des routes, comportant l’information de leur longueur (en km). Toutes les villes sont supposées être reliées par au moins une route. Ces routes sont toutes en double sens.
un reseau social de type Facebook, où les participants ont des liens d’amitié entre-eux. Ce lien est réciproque (si Marcel est ami avec Justine, alors Justine est aussi amie avec Marcel). Les sous-reseaux ne sont pas tous reliés entre eux. (Il existe au moins deux groupes A et B complètement indépendants: aucune des personnes de A n’est amie avec celles de B).
un reseau social de type Twitter: les participants ont des folowers. Cette relation n’est pas réciproque. Les folowers suivent les participants qui partagent les même centres d’intérêt.
une partie de jeu de morpion (tic-tac-toe), où les états de la partie sont liés aux états suivants possibles.
Implémentations
Plusieurs modes de représentation sont possibles pour stocker des graphes: matrices d’adjacence, listes des voisins, des successeurs ou des prédécesseurs. On peut les classer en 2 catégories:
Les représentations matricielles
Les représentations sous forme de liste chainée
Liste de voisins et matrice d’adjacence
Liste de voisins
Un exemple simple présente ici un graphe créé à partir d’une liste de voisins:
[[1, 2], [0, 2, 3], [0, 1, 3], [1, 2]]
La première sous-liste correspond aux liens que forme le sommet 0. Ici, c’est donc avec les sommets 1 et 2.
C’est aussi la représentation d’une liste chainée.
Liste d’adjacence
Cette liste L peut aussi être mise sous forme d’une matrice M:
Simplifions la représentation de ce reseau social en un Graphe:
avec etiquettes aux sommets
Et utilisons la matrice d’adjacence pour indiquer le plus cours chemin d’un sommet à l’autre.
matrice des distances entre sommets
Ainsi, une fois la matrice établie, nous pouvons en déduire le diamètre de ce graphe (plus grande longueur entre 2 sommets du graphe). Ici, cette distance vaut 3.
Dans un graphe plus grand, la détermination du plus court chemin entre 2 sommets necessite une méthode basée sur un algorithme. Par exemple, l’algorithme BFS ou bien l’agorithme de Dijkstra.
Graphe avec étiquette
On utilisera un dictionnaire comme structure de données. Les clés étant les étiquettes des sommets, et les valeurs, la liste des sommets adjacents:
Question: Représenter la matrice d’adjacence équivalente.
Liste (chainée) de successeurs
Cette représentation est particulièrement adaptée aux graphes orientés.
graphe orienté
On peut représenter un graphe avec une liste chaînée des successeurs:
sommet => liste de sommets liés suivants
0 => 1, 2
1 => ...
2 => ...
3 => ...
Le sommet 0 aura alors 2 successeurs, les noeuds 1 et 2.
Question: Compléter la liste de successeurs
L’implémentation utilise le même principe que pour une liste chainée linéaire. Sauf qu’ici, le nombre de successeur est supposé être supérieur à 1.
Il y aura alors plus d’un attribut suiv. Supposons que le degré sortant maximum est égal à 3:
classSommet:def__init__(self,val,suiv1=None,suiv2=None,suiv3=None):self.val=val# etiquette du sommetself.suiv1=suiv1self.suiv2=suiv2self.suiv3=suiv3S2=Sommet(2)S1=Sommet(1)S0=Sommet(0,1,2)
Liste (chainée) de predecesseurs
Il peut être necessaire d’établir aussi, pour chaque sommet, une liste de predecesseurs:
Le parcours d’un graphe va donner une liste d’arcs ou de sommets visités, dans un certain ordre.
Cet ordre va dépendre de l’algorithme employé: Pour des parcours de type largeur ou profondeur, on suppose que l’on peut revenir sur ses pas. La liste de sommets ne représente pas un chemin.
On appelera chemin une suite continue de sommets (ou d’arcs) consécutifs dans le graphe, sans retour en arrière, c’est à dire sans revenir vers un sommet déjà visité.
Parcours d’un graphe en largeur BFS
Principe: BFS (Breadth-First Search): Il s’agit d’une exploration du graphe G, de proche en proche, en explorant tous les chemins, depuis la distance de longueur 1 du sommet, puis la distance 2, …
Soit G(V,E) un graphe de sommets V = {A,B,C,D,E,F,G,H,I,J} et d’arêtes E.
On note la distance entre 2 sommets quelconques u et v dans le graphe G :
$$dist_G(u,v)$$
Pour le graphe exemple suivant (Graphe 1), la distance du sommet A au sommet J, vaut au minimum 4 (chemin A, B, E, I, J). Mais cela depend du chemin. Ainsi :
$$dist_G(A,J)=4$$
.
Graphe 1 : exemple
Calculons toutes les distances dans ce graphe : L’algorithme de parcours en largeur (Breadth-First Search BFS)
Principe :
Pour déterminer la longueur de tous les chemins du graphe, il va falloir le parcourir. Lors du parcours, certains sommets seront colorés, pour nous rappeler qu’ils ont été parcouru (rouge), ou en cours de parcours (vert).
On aura besoin de conserver une liste L des sommets à explorer.
On commence l’exploration en partant d’un sommet r. Voici la méthode :
Colorer en VERT le sommet r pour se rappeler qu’il a déjà été partiellement traité.
Parcourir le graphe depuis r jusqu’à l’un de ses voisins u, non coloré en vert ou rouge. Colorer u en VERT.
Noter la distance du sommet de départ r vers le sommet u en cours d’exploration : distG(r,u) = 1 si le sommet voisin u est adjacent.
Ajouter le nom du sommet u à droite dans la liste L: L = [r,u]
Si r a d’autres sommets adjacents, revenir au point 2 et explorer un autre de ces sommets (points 2, 3, 4).
Si r n’a plus de sommet adjacent non visité, colorer r en rouge. Retirer r de la liste (premier sommet, à gauche dans la liste L). L ayant une structure de FILE, on dit que l’on défiler.
On poursuit ensuite l’exploration à partir du nouveau premier sommet v adjacent de u. La distance de r à v est alors : distG(r,v) = distG(r,u) + 1 (point 3).
Lorsque la liste L est vide, l’exploration est terminée et toutes les distances entre r et les autres sommets est connue.
Exemple :
A partir du graphe 1 défini plus haut, on démarre l’exploration à partir du sommet r = E.
Celui ci est coloré en VERT.
La méthode vue plus haut permet de rapidement établir la liste L = [E,B,F,H,I] à partir des sommets adjacents à E. Les sommets B,F,H,I sont à une distance 1 du sommet E. On a par exemple distG(E,B) = 1. Ces sommets sont colorés en VERT.
Une fois cette première partie de l’exploration terminée, on retire E de la liste L, et on colore le sommet en rouge.
L = [B,F,H,I]
On note la distance au sommet E pour chacun des sommets visités, le symbole ∞ pour ceux qui ne l’ont pas encore été:
exploration depuis le sommet…
A
B
C
D
F
G
H
I
J
E
∞
1
∞
∞
1
∞
1
1
∞
On se déplace maintenant sur le sommet B, qui est le premier de la liste.
L’exploration de ses sommets adjacents continue, à conditions que ceux-ci soient blancs, sinon, on passe à un autre sommet. Ici, on fait l’exploration des sommets A,C,D. Ceux-ci sont colorés en VERT, et ajoutés à la liste L:
$$L = [F,H,I,A,C,D]$$
Les distances de E à chacun de ces nouveaux noeuds sont enregistrées :
distG(E,A) = 2, tout comme distG(E,C) et distG(E,D). Le tableau suivant donne les distances depuis le sommet E:
exploration depuis le sommet…
A
B
C
D
F
G
H
I
J
B
2
2
2
∞
∞
Les distances déjà connues ne sont pas modifiées. On laisse un blanc dans le tableau.
On colore ensuite le sommet B en rouge et on le retire de la liste L.
L = [F,H,I,A,C,D]
Ensuite, depuis le sommet F: on explore le graphe jusqu’au sommet G, seul sommet adjacent encore blanc.
On a alors distG(E,G) = 2, puis le sommet F est mis en rouge et retiré de la liste:
$$L = [H,I,A,C,D,G]$$
exploration depuis le sommet…
A
B
C
D
F
G
H
I
J
F
2
∞
On poursuivra l’exploration par le sommet H, suivant dans la liste. Ce qui permettra de définir le dernier chemin jusqu’à J, et noter distG(E,J) = 2:
exploration depuis le sommet…
A
B
C
D
F
G
H
I
J
H
2
A la fin du traitement, on peut représenter à l’aide d’un arbre tous les chemins issus de l’exploration du graphe :
arbre du parcours BFS
Pour réaliser cet arbre, il y aura 2 méthodes:
Soit la construction d’un tableau des sommets visités au fur et à mesure de l’exploration (vu plus haut)
Soit remonter chaque étape du parcours du graphe le parent du sommet visité. (voir fiche d’exercices). Ainsi, il aura faudra se rappeler que le sommet D a pour parent le noeud B (D est marqué dans le tableau dont l’entrée est B). Et le sommet B a lui même pour parent le sommet E. Ainsi, en remontant le chemin, on sait que le chemin de E à D passe par B : E => B => D.
Pour aller plus loin (term NSI)
Consulter la page du parcours en largeur sur wikipedia
Application de l’algorithme BFS au parcours dans un labyrinthe:
video: Maze Pathfinder - Breadth First Search (BFS)
Parcours d’un graphe en profondeur (DFS)
Principe: L’exploration DFS (Depth-First Search) retourne une liste de sommets, parcourus en plongeant dans la profondeur du graphe. Le prochain sommet visité est un des successeurs du sommet courant, avec un retour en arrière lorsque’il n’y a pas de nouveau successeur, ou bien lorsque celui-ci a deja été visité.
Voici les 2 programmes python de parcours en profondeur d’un graphe:
defDFS_ite(d,s,visited=[],stack=[]):stack.append(s)whilestack:v=stack.pop()ifvnotinvisited:visited.append(v)unvisited=[nfornind[v]ifnnotinvisited]stack.extend(inverse(unvisited))returnvisiteddefinverse(L):# fonction utile pour avoir le meme ordre de parcours # des sommets adjacents, pour les fonctions DFS et DFS_itereturn[L[i]foriinrange(len(L)-1,-1,-1)]
Remarque: La fonction inverse est utile pour avoir les mêmes parcours DFS, en itératif et récursif. On peut la programmer comme ci-dessus, ou bien en utilisant un slice de la manière suivante: stack.extend(univisited[::-1])
L=[1,2,3,4]L=L[::-1]# copie par valeur de la liste inverséeprint(L)# affiche [4,3,2,1]
Principe
Soit un graphe G = (V,E) et r un sommet de G, point de départ de l’exploration.
Le parcours en profondeur du graphe va permettre de visiter tous les noeuds du graphe, mais selon un chemin où l’on plonge dans la profondeur du graphe. Le prochain sommet visité sera un sommet fils non encore visité.
A chaque étape, c’est à dire à chaque arête suivie, il faudra mémoriser le parent du nouveau sommet visité. (une fois celui-ci placé dans la liste des sommets parcourus, pas découverts). Cela permettra de revenir en arrière. On utilisera pour cela une structure de PILE. On reviendra en arrière en dépilant le dernier sommet de la liste.
Lorsque le chemin mène à une impasse, (il n’y a plus de sommet fils non visité), lorsque l’on est sur un bord du graphe, alors on remonte d’un niveau, vers un sommet parent, avant de poursuivre l’exploration.
En pratique :
tous les sommets ont d’abord colorés en BLANC.
On colore chaque noeud u visité en VERT.
Lorsque tous les noeuds fils de u sont visités, on colore celui-ci en ROUGE.
Illustration :
Avec le graphe suivant, on démarre l’exploration du noeud G :
exemple de graphe pour le parcours en profondeur
La première étape est la phase de descente : On peut démarrer l’exploration par le sommet voisin A ou B. Les deux sont possibles. Ils sont de couleur BLANCHE.
Supposons que l’on commence l’exploration par B (on aurait tout aussi bien choisir le A). On colore alors B en VERT.
On poursuit l’exploration par les sommets suivants : D,C,A (il y a d’autres possibiltés) :
étape 1
Le sommet A est un bord du graphe : il n’y a pas de noeud fils BLANC. On remonte alors d’un niveau : jusqu’au sommet C. Celui ci ne presente pas davantage de voisin BLANC. A et C sont colorés en ROUGE et on remonte à D.
On peut alors poursuivre l’exploration vers E :
étape 2
Depuis le sommet E, on peut visiter F et I. Choisissons F (mais on pourrait choisir également I) :
étape 3
On poursuit l’exploration jusqu’en I. Tous les sommets sont visités, et l’exploration est terminée.
fin du parcours
Le schéma suivant illustre le parcours réalisé à partir des arêtes empruntées. Il s’agit d’un arbre couvrant le graphe :
arbre couvrant
Applications
Le parcours d’un graphe en profondeur s’apparente à un algorithme de type retour sur trace, ou backtracking. C’est le comportement de joueur que l’on a lorsque l’on a droit à un nouvelle chance :
Dans un jeu d’echec, lorsque l’on joue contre l’ordinateur, une option permet de revenir en arrière. On peut revenir un coup en arrière et prendre une meilleure option. L’ordinateur construit un graphe au fur et à mesure du jeu avec les coups joués ainsi que la configuration du jeu, afin de permettre ce backtracking.
Lorsque l’on joue à un jeu de labyrinthe (illustration site zestedesavoir): Si on arrive dans une impasse, on adopte là aussi un algorithme de type retour sur trace. On revient jusqu’au noeud parent (le croisement précédent) afin d’explorer une nouvelle voie. Et si toutes ces voies sont sans issues, on remonte encore d’un niveau (le croisement précédent encore celui ci).
Parcourir un graphe pour trouver TOUS les chemins
Il s’agit d’une variante du parcours en profondeur.
Pour un graphe G, le problème s’énonce de la manière suivante:
Pour un sommet de départ A, créer un nouveau chemin pour chaque sommet adjacent à A de la manière suivante:
Commencer le chemin avec la liste de sommets [A]
Si le sommet adjacent est un nouveau sommet, n’appartenant pas déjà un chemin.
ajouter le nouveau sommet adjacent au chemin, par exemple [A,B]
ajouter ce chemin à la liste des chemins
continuer avec cette même méthode depuis le sommet adjacent (appel recursif avec le sommet adjacent comme nouveau départ, et placer chemin en paramètre)
Un arbre est constitué de noeuds organisés de manière hierarchique: c’est un graphe non orienté, connexe, sans cycle, dans lequel on a choisi un noeud particulier appelé la racine.
Chaque noeud peut être étiqueté par une information.
l’arbre généalogique est un bon exemple. Le vocabulaire sur la structure des arbres s’inspire d’ailleurs de la génélogie (père-fils).
family tree sur freepik.com/genealogie
Les noeuds sont …les couples.
L’arbre représentant les sytèmes de dossiers sur ordinateur (dossiers et sous-dossiers puis fichiers)Ci-dessous l’arborescence de fichiers dans un raspberry-Pi:
Les arbres sont très utilisés en informatique, d’abord parce que les données sont souvent hierarchisées, et se prêtent bien à cette structure. Mais aussi parce que l’accès à ces données est alors plus efficace: la recherche d’une valeur se fait en O(log(n)) dans le cas moyen, où n est la taille de l’arbre.
Caractéristiques d’un arbre
exemple d'arbre binaire et vocabulaire
Dans un arbre, chaque valeur est stockée dans un nœud. On appelle parfois cette valeur une clé.
Les nœuds sont connectés par des arêtes, ou branches qui représentent une relation de type “parent (prédécesseur est le terme exact) – fils”.
Chaque noeud ne possède qu’un seul noeud parent (sauf le noeud racine).
La racine est le seul nœud qui n’a pas de prédécesseur.
Les nœuds qui n’ont pas de fils sont appelés des feuilles.
Des nœuds qui ont le même père sont appelés des frères.
Un sous-arbre c’est une portion de l’arbre. C’est une notion utile pour la recursivité.
Le niveau d’un nœud est la distance qui le sépare de la racine… Sachant que le niveau de la racine est 0 et que le niveau d’un nœud quelconque c’est 1+ le niveau de son père.
La hauteur d’un arbre, ou sa profondeur est égale au niveau (à la profondeur) du noeud le plus profond. Selon la convention proposée ici (le niveau de la racine vaut 0), la hauteur correspond aussi au plus grand nombre de branches depuis la racine jusqu’à l’une de ses feuilles.
Le degré d’un arbre est egal au plus grand des degrés de ses noeuds.
Un arbre de degré égal à 1 est … une liste.
Quel est le degré de cet arbre?
La taille d’un arbre est son nombre de noeuds.
dimensions d'un arbre
Arbres binaires
Arbre binaire: arbre de degré égal à 2. Chaque noeud a au plus 2 fils: le fils droit et le fils gauche.
Arbre binaire équilibré: pour chaque noeud interne, les sous-arbres gauche et droit ont une même hauteur (ou qui diffère d’une unité).
Arbre binaire complet: tous les niveaux de l’arbre sont remplis.
La taille d’un arbre binaire peut alors se déduire de la formule, qui prend la profondeur p en paramètre:
$$T = \sum_{0}^{n-1} 2^p = 2^n-1$$
definition recursive des arbres binaires
arbre complet
Implémenter en python
On utilisera l’arbre suivant pour l’implémentation en python:
exemple d'arbre binaire de taille 9
Comme vu pour les graphes, on pourra utiliser des listes imbriquées, un dictionnaire, ou une classe (programmation objet).
Liste
Un noeud peut être représenté par une liste imbriquée [clé,fils gauche,fils droit].
Et comme les fils gauche ou fils droit sont des noeuds, on y mettra une nouvelle liste imbriquée [clé,fils gauche,fils droit].
Pour les feuilles, la liste s’écrit: [clé,None,None].
Le petit arbre suivant peut être représenté par ['r',[‘a’,None,None],[‘b’,None,None]]`
petit arbre de taille 3
Avec l’arbre de taille 9 donné en exemple:
arbre9 = [3,[...,..,..],[...,..,..]]
Question: compléter cette liste.
Classe
La classe suivante va permettre d’implémenter les arbres binaires:
On n’a donné ici que le constructeur, mais il est possible d’y ajouter les méthodes qui permettront de retourner une valeur (getter), ou d’ajouter un noeud (setter); ou encore de déterminer les dimensions de l’arbre.
Avec l’arbre de taille 9 vu plus haut, la classe peut s’utiliser de la manière suivante (avec la notation pointée qui n’est pas recommandée):
Definition: Un parcours est un algorithme qui appelle une fonction, ou un méthode sur tous les noeuds d’un arbre.
L’ordre sur les noeuds dans lequel la méthode est appelée doit être fixé. Il y a plusieurs choix, qui diffèrent par la seule position de l’instruction Afficher clef [ r ]
L’algorithme opère alors un traitement sur chacune des clés de l’arbre, dans un ordre choisi. Ici, on cherche à Afficher la clef.
Mais on peut remplacer cette instruction par un traitement sur les valeurs: ajouter 1 pour compter les clés par exemple.
Parcours postfixe
ParcoursPostfixe ( Arbre binaire T de racine r )
ParcoursPostfixe(Arbre de racine fils_gauche[r])
ParcoursPostfixe(Arbre de racine fils_droit[r])
Afficher clef [ r ]
Parcours préfixe
ParcoursPréfixe ( Arbre binaire T de racine r )
Afficher clef [ r ]
ParcoursPréfixe(Arbre de racine fils_gauche[r])
ParcoursPréfixe(Arbre de racine fils_droit[r])
Parcours infixe
ParcoursInfixe ( Arbre binaire T de racine r )
ParcoursInfixe(Arbre de racine fils_gauche[r])
Afficher clef [ r ]
ParcoursInfixe(Arbre de racine fils_droit[r])
exemples de parcours
Parcours en largeur
Les trois algorithmes vus plus haut s’apparent à une exploration de type parcours en profondeur. C’est la position de l’instruction de traitement qui amène les différences entre ces 3 parcours.
Un arbre est un graphe. On peut donc lui appliquer l’algorithme de parcours en largeur vu dans une leçon précédente.
TP Filius simulation d’un reseau, table de routage
Sous-sections de architecture
fichiers
Gestion des fichiers et systemes d’exploitation
Pourquoi des fichiers?
Le processeur et le coeur du système d’exploitation (le noyau) s’associent pour optimiser au mieux l’usage de la mémoire principale grâce aux espaces de mémoire virtuelle, alloués au processus. Cependant cette mémoire est de taille limitée, et ne conserve pas son état lors d’une coupure de l’alimentation. Pour répondre à ces problèmes, le système d’exploitation propose à l’utilisateur et au processus un système de fichiers.
Un fichier est une zone mémoire physique de taille limitée stockant des données de manière persistante.
Cette mémoire dite secondaire, est une mémoire de stockage ou mémoire de masse. Elle peut être un disque dur un CD une carte mémoire SD etc. Ces données stockées sur un tel support doivent pouvoir être relus une fois la mémoire RAM éteinte. On peut aussi vouloir déplacer un disque et l’utiliser sur un système d’exploitation qui n’a aucune information a priori sur le contenu de ce disque.
Les applications ont justement besoin de fichiers pour stocker leurs programmes et pour sauvegarder des données.
Système de fichiers, organisation dans le disque physique
On peut distinguer deux types de fichiers:
les fichiers texte écrit en ascii ou UTF-8. Chaque octet ou chaque mot de 16 bits correspond à un caractère.
les fichiers binaires. Le fichier n’est qu’une liste de nombres sans sens si on ne connaît pas le format et le logiciel associé. Ce format est annoncé par une extension.
Chaque fichier a un nom, dont une extension (obligatoire sous Windows facultatif sous Linux): txt, docx, html, json, jpg, mp3, …
Un fichier est une collection de données numériques qui se partagent entre des données (principales), et des métadonnées (quelques dizaines d’octets). Les metadonnées sont la taille, la date de création et/ou de modifications, le propriétaire, les droits d’accès, et l’adresse sur le disque.
Le système de fichiers gère la structuration le nommage l’accès la protection et l’implantation des fichiers, avec les adresses des blocs sur le disque physique.
Plusieurs systèmes de fichiers co-existent (FAT32 et NTFS pour Windows, EXT4 Linux). Ces informations sur le contenu du disque ainsi que sur les fichiers sont rappelés dans un super bloc, au début de la partition, ce qui permet de déplacer le disque et le lire avec un autre système. Il comporte toutes les informations nécessaires à la compréhension de son système de fichiers.
Le rôle du système d’exploitation
Le système d’exploitation vérifie les droits d’accès en lecture/écriture/exécution. Il peut verrouiller tout ou partie d’un fichier, ainsi que l’accès simultané en écriture à un même fichier par deux processus, ce qui pourrait le corrompre. Enfin, il copie une partie du fichier, la plus interessante selon le processus, sur la mémoire RAM. Au final, un processus n’a jamais vraiment accès au fichier lui-même, mais à une représentation, sur la RAM.
Pour faciliter l’accès aux fichiers, les systèmes d’exploitation présentent ceux-ci selon une arborescence de dossiers appelés aussi repertoires.
Pour accéder à un fichier, il faut donc indiquer un chemin.
Un dossier est alors un simple fichier indiquant les fichiers et les dossiers (donc des fichiers), à l’interieur.
L’opération dite de montage revient à associer à un dossier un système de fichiers différents. Cela se fait lorsque l’on connecte par exemple une clé usb.
Les systèmes d’exploitation graphiques (MS Windows, Linux Ubuntu, Mac OS, …) disposent de logiciel d’exploration des fichiers, et associent à chaque type de fichier un pictogramme appelé icône.
Linux
Sous Linux, tout est fichier. Il y a 4 catégories de fichiers:
fichiers normaux (fichiers textes, sources de programmes, fichiers binaires, …)
fichiers répertoires: des fichiers containers, qui contiennent des références vers d’autres fichiers
fichiers speciaux: situés sous /dev, ce sont les points d’accès vers les peripheriques.
les fichiers liens symboliques: ne contiennent qu’une référence vers un autre fichier. (les raccourcis sous windows) Cela permet d’avoir un même fichier, à differents emplacements, avec des noms différents.
Ainsi, lorsque l’on branche un nouveau disque physique, un chemin d’accès est defini dans l’arborescence du système (par exemple /media/fred)
Windows
Dans le monde Windows, contrairement aux systèmes Linux, les partitions et périphériques de stockage possèdent leur propre arborescence, dont la racine porte un nom d’une seule lettre : A: C: D: …
Manipulation des fichiers et dossiers
Les systèmes d’exploitation courants possédent une interface graphique et ont des logiciels d’exploration évolués et intuitifs (Explorateur de fichiers sous Windows, Gestionnaire de fichiers sous Ubuntu, …). L’explorateur permet de:
naviguer aisément dans l’arborescence,
déplacer/copier/coller des fichiers et des dossier, y compris par glisser/déposer,
*lancer des applications et ouvrir des documents,
obtenir des informations avancées sur les fichiers et dossier (métadonnées),
réaliser des recherches de fichiers et dossiers,
créer de nouveaux documents,
…
Mais ce n’est pas la seule façon de naviguer dans l’arborescence: les systèmes d’exploitation permettent aussi de réaliser ces fonctions en ligne de commande, à partir d’un terminal (une fenêtre qui interface l’utilisateur avec un interpreteur).
En informatique, un système d’exploitation (souvent appelé OS — de l’anglais Operating System) est un ensemble de programmes qui dirige l’utilisation des ressources d’un ordinateur par des logiciels applicatifs. Lien Wikipedia
Il reçoit des demandes d’utilisation des ressources de l’ordinateur — ressources de stockage des mémoires (par exemple des accès à la mémoire vive, aux disques durs), ressources de calcul du processeur central, ressources de communication vers des périphériques (pour parfois demander des ressources de calcul au GPU par exemple ou tout autre carte d’extension) ou via le réseau — de la part des logiciels applicatifs. Le système d’exploitation gère les demandes ainsi que les ressources nécessaires évitant les interférences entre les logiciels.
Processus et blocages
Définitions
Exécution d’un programme: le lancement d’un programme entraîne des lectures et écritures dans des registres et une partie de la mémoire. Le microprocesseur réalise des opérations sur les données mises dans les registres.
Un processus représente une instance d’exécution d’un programme dans une machine donnée, qui a sa propre zone mémoire virtuelle.
Les états d’un processus
Les systèmes d’exploitation sont capables de gérer l’execution de plusieurs processus en même temps. En réalité, ce n’est pas tout à fait en même temps: pour gérer ce chacun son tour, les systèmes d’exploitation attribuent des états au processus.
Ces états sont résumés ci-dessous.
Lorsqu’un processus est créé, il démarre dans l’état prêt: il attend l’accès au processeur.
Le processus obtient, grâce au systeme d’exploitation, l’accès au processeur. Il passe alors dans l’état élu.
Alors qu’il est élu, le processus peut avoir besoin d’attendre une ressource quelconque comme, par exemple, une ressource en mémoire ou sur le disque dur. Il doit alors quitter momentanément le processeur pour que celui-ci puisse être utilisé à d’autres tâches (le processeur ne doit pas attendre!). Le processus passe donc de l’état élu à l’état bloqué. (c’est un blocage)
Lorsque le processus a obtenu la ressource attendue mais s’est fait prendre sa place dans le processeur par un autre processus, il se met en attente: C’est l’état prêt, en attente que la place se libère. Cette étape, de bloqué à prêt est l’opération de déblocage.
Le passage de l’état prêt vers l’état élu constitue l’opération d’élection.
Un processus ne pourra terminer que s’il est déjà dans l’état élu.
mecanisme d'election
Un processus peut créer un ou plusieurs nouveaux processus. Il y a alors une filiation père-fils.
Chaque processus possède un numéro PID qui lui est attribué automatiquement. Il possède aussi un PPID qui est le numéro d’identification du processus père.
Ordonnancement
Plusieurs processus peuvent être dans l’état prêt: comment choisir celui qui sera élu?
L’ordonnanceur (sheduler) classe les processus prêts dans une file et les fait passer du statut prêt à élu (et inversement). Il planifie l’exécution des processus.
Dans les systèmes d’exploitation, l’ordonnanceur désigne le composant du noyau du système d’exploitation choisissant l’ordre d’exécution des processus sur les processeurs d’un ordinateur. Cette organisation permet d’occuper au mieux le (ou les) processeurs.
gestion des processus
Il existe plusieurs politiques d’ordonnancement dont le choix va dépendre des objectifs du système. Voici quelques exemples:
• Premier arrivé, premier servi: simple, mais peu adapté à la plupart des situations.
• Plus court d’abord: très efficace, mais il est la plupart du temps impossible de connaître à l’avance le temps d’exécution d’un processus.
• Priorité: le système alloue un niveau de priorité aux processus (SCHED_FIFO sur Linux). Cependant des processus de faible priorité peuvent ne jamais être élus.
• Tourniquet: un quantum de temps est alloué à chaque processus (SCHED_RR sous Linux). Si le processus n’est pas terminé au bout de ce temps, il est mis en bout de file en état prêt.
• Un système hybride entre tourniquet et priorité qu’on retrouve dans les systèmes Unix.
Interblocage
Concurents mal synchronisés
L’ordonnanceur fait passer les processus de élu à commuté. Mais Il peut y avoir une situation où 2 processus sont interbloqués car:
P1 possède la ressource R1 mais souhaite R2: commutation pour P2
P2 possède la ressource R2 mais souhaite R1: commutation pour P1
Dans cette situation, les deux processus légers sont définitivement bloqués.(wiki)
Des solutions de détection/guérison peuvent être mises en place.
Définition sur Wikipedia
Deux processus en concurrence pour deux ressources dans un ordre opposé. Voici une chronologie possible qui mène à un interblocage.
A) Un seul processus se déroule.
B) Le processus ultérieur doit attendre.
C) Un blocage se produit lorsque le premier processus verrouille la première ressource en même temps que le second processus verrouille la seconde ressource.
D) Le blocage peut être résolu en annulant et en redémarrant le premier processus.
Modélisation par un graphe orienté
Il y a interblocage lorsque des cycles sont présents dans le graphe réalisé de la manière suivante:
un arc de la ressource Ri au processus Pj signifie que le processus Pj a obtenu la ressource
un arc Pj vers Ri signifie que le processus Pj demande la ressource Ri.
interblocage - wikipedia
Exemple: le processus P1 utilise la ressource R2 qui est attendue par le processus P2 qui utilise la ressource R1, attendue par P1.
Illustration d’un interblocage routier
saurez vous modéliser la situation suivante par un graphe présentant un cycle?
Gestion des tâches par une même application
Un thread est un élément d’un processus qui va partager avec un programme l’espace des données et va s’exécuter de façon simultané avec d’autres thread. On parle aussi de processus légers.
Plusieurs threads peuvent exister dans le même processus. Ces threads partagent la mémoire et l’état du processus. En d’autres termes: ils partagent le code ou les instructions et les valeurs de ses variables.
partage des ressources par 3 threads
Ils peuvent aussi causer de multiples problèmes (accès concurent, interblocage).
On a vu un problème identique sur la gestion concurente des accès à une même ressource sur le chapitre sur les SGBD.
l’usage de datagrammes pour transmettre l’information
le routage de ces datagrammes par des ordinateurs spécialisés, … les routeurs.
Le reseau internet est un reseau qui connecte entre eux des reseaux, à l’echelle mondiale. Voir lien vers la page Reseaux de seconde SNT pour revisions
Le datagramme: les informations échangées
Dans le modèle TCP/IP, les ordinateurs peuvent établir et réaliser une communication selon plusieurs couches, qui cloisonnent les logiciels et technologies utilisées. D’après la norme, les couches vont de la plus haute (couche 7: l’utilisateur) à la plus basse (couche 1: support physique).
Lorsque vous envoyez une requête ou un fichier à une machine distante, les logiciels installés vont fabriquer des trames de 1500 octets, dont le datagramme contient les données utiles pour la transmission (dont l’adresse IP du destinataire et de l’emetteur), et les informations à transmettre, le tout sous format binaire.
Souvent, les informations à transmettre occupent un poids trop important pour être placées dans une trame de 1500 octets. Il faudra alors plus d’une trame pour envoyer les différents paquets, qui devront être reconstruits à l’arrivée.
Durant le trajet à travers les différentes couches du modèle OSI, 4:application, 3:transport, 2:internet et 1: hôte-réseau , le datagramme subira des modifications et chaque couche rajoutera ce qu’elle voudra:
La couche 4:transport va ajouter les informations utiles pour contrôler l’arrivée l’ordre des paquets envoyés: résolu par le protocole TCP.
La couche 3:internet va ajouter les informations utiles pour interconnecter les réseaux: résolu par le protocole IP.
Ce mécanisme s’appelle l’encapsulation, car les données de la couche 2 vont contenir celles de la couche 3, etc…
Ainsi, à la sortie de la couche 2, la requête HTTP issue de votre navigateur est transformée en une série de données que l’on peut segmenter en:
[en-tête Ethernet, wifi ou 4G][en-tête IP][en tête TCP][requête HTTP][checksum Ethernet]
La machine distante, qui reçoit cette trame, va alors repondre immédiatement en envoyant un accusé de reception.
principe de l'emission - reception d'une trame sur internet
Les machines reliées dans le réseau internet peuvent être:
un ordinateur (machine hôte)
une imprimante
un commutateur (switch) : mis en reseau de manière centralisée, n’a pas d’adresse IP, agit au niveau de la couche 2, connecte les machines dans le sous-reseau, sert à envoyer les trames au destinataire direct, ne possède pas d’adresse IP.
routeur : transporte les paquets même s’ils ne lui sont pas adressés directement, choisit la meilleure route, joint plusieurs réseaux, agit au niveau de la couche 3.
Un routeur possède plusieurs cartes réseaux. Chacune de ces cartes réseau est liée à une interface, possédant une adresse IP, en rapport avec le sous-reseau auquel l’interface est reliée.
Sur le routeur suivant, il y a 3 ports ethernet, ainsi qu’une antenne wifi. Ce qui fait 4 cartes reseau:
routeur de la marque Siretta
On suppose qu’une carte reseau propose une seule interface (une porte vers le sous-reseau directement relié), et possède donc une seule adresse IP.
Adresse IP
Dans le reseau internet, les reseaux et les machines sont identifiés par un numéro unique, l’adresse IP. Pour être exact, ce sont les cartes reseaux des machines qui possèdent une adresse IP.
Une adresse IP de la norme IPv4 est un nombre binaire codé sur 32 bits, soit 4 octets. Le nombre d’adresses possibles est alors de plus de 4 milliards.
Exemple d’adresse IPv4 exprimée à l’aide de 4 valeurs décimales (0-255):
192.168.0.1/24
La notation utilisant CIDR composé d’une adresse IPv4 et d’une indication sur le masque de sous réseau. Par exemple : 192.168.0.1/24 signifie :
Adresse IP : 192.168.0.1
Masque de sous-réseau en notation CIDR : 24
partie reseau de l’adresse: 24 premiers bits, c’est à dire les octets 192.168.0
partie machine de l’adresse IP: les 8 derniers bits (32 - 24), soit le dernier octet: .1
Machines appartenant à un même reseau
Definition: Deux machines sont sur le même réseau si et seulement si, les parties réseau de leur adresse IP sont identiques.
Les derniers caractères /24 correspondent au masque de sous-reseau. Ils signifient que le reseau contenant la machine a une adresse codée sur les 24 premiers bits (192.168.0). Et que les 8 derniers bits constituent l’adresse de la machine dans ce reseau (il s’agit donc du .1 final).
Le masque de sous-reseau peut être aussi exprimé sous la forme binaire. Les N premiers chiffres du masque valent alors 1 et les autres (jusqu’au 32e) valent 0. Par exemple:
/8 correspond à 11111111 00000000 00000000 00000000.
Il est alors plus commode d’écrire l’equivalent décimal pour chacun des bits:
255.0.0.0
Remarque sur la norme IPv6
Pour la norme IPv6, ce nombre est sur 128 bits, soit 16 octets.
Exemple d’adresse IPv6 exprimée en hexadécimal (32 caractères):2001:0db8:3c4d:0015:0000:0000:1a2f:1a2b
Voir l’exercice n°1 du sujet de Baccalaureat: Metropole Sept 2021: reseau d’ordinateurs
Table de routage (reseau local)
Chaque routeur reçoit des données et doit décider à qui les transmettre. Pour cela, il dispose de tables de routage construites soit statiquement (par un humain), soit dynamiquement (par un programme).
Lorsqu’il reçoit un message (une trame), il lit l’adresse IP du destinataire et le redirige dans la bonne direction:
soit le routeur est directement relié au bon reseau, contenant le destinataire: le message va alors circuler par la carte reseau correspondante (l’adresse Passerelle (Gateway)).
soit l’adresse lui est inconnue: c’est sa table de routage qui va lui dire à quel autre routeur l’envoyer.
La table de routage contiendra donc:
les adresses IP des reseaux et des passerelles (cartes reseaux) auxquels le routeur est directement relié.
l’adresse IP 0.0.0.0 (celle d’internet) sera associée à la passerelle qui fera circuler le message vers internet. Ce sera l’adresse IP du routeur voisin qui pourra acheminer ce message vers internet.
les adresses IP des reseaux auxquels le routeur n’est pas directement lié. La passerelle sera l’adresse de la carte reseau du routeur voisin qui mène à ces reseaux.
Exemple:
Dans cette représentation, on donne l’adresse des réseaux lorsqu’il y a plusieurs connexions. Par exemple 192.168.1.0/24 pour le reseau en bas à gauche. Pour toutes les machines connectées, on ne donne que la partie adresse machine. Il s’agit du dernier octet de l’adresse IP.
système n°1
La table de routage du routeur 1 est alors:
reseau à rejoindre
passerelle (Gateway)
192.168.0.0/24
192.168.0.254
192.168.1.0/24
192.168.1.254
0.0.0.0
192.168.1.253
10.0.0.0/24
192.168.0.253
Remarque: La table de routage du logiciel Filius donne également l’adresse 127.0.0.0/ 255.255.255.255. Cette adresse est réservé pour le bouclage, c’est-à-dire l’auto-adresse d’un hôte, également connue sous le nom d’adresse localhost. Cette adresse IP de bouclage est entièrement gérée par et dans le système d’exploitation et ne renvoie pas vers un port du routeur.
plusieurs machines hôtes, partagées dans les 4 reseaux
une passerelle vers internet
Les adresses IP indiquées sur le schéma suivant concernent toutes les cartes reseaux des machines. Les routeurs possèdent une carte reseau par interface reseau.
exemple d'un reseau de sous-reseaux
Dans cet exemple, voici la liste des adresses IP des différents reseaux:
Pour un reseau de petite dimension, on peut envisager d’utiliser une table de routage statique, comme vue dans le cours graphes et internet.
Par contre, pour des reseaux de grande taille, il faudra une méthode permettant de construire et mettre à jour cette table de manière dynamique. Il existe 2 protocoles pour réaliser cela, RIP et OSPF.
Ces protocoles vont permettre aux routeurs d’échanger des informations entre eux, afin d’avoir un aperçu des réseaux autour d’eux. Ils vont déterminer le meilleur chemin en fonction de l’état du réseau. Ils se basent sur un critère, ou plutôt un coût associé à chaque chemin: il s’agira du nombre de sauts (routeurs traversés) ou bien de l’estimation de la durée d’acheminement (loi sur le débit).
Ces protocoles doivent eviter les boucles de routage, et corriger les données de routage selon l’evolution du reseau (nouvelles machines, ou pannes, engorgement).
Chaque modification du reseau va entrainer un temps d’echange entre les routeurs, jusqu’à ce que ceux-ci finissent par établir une nouvelle table de routage.
Routages dynamiques:
Les routeurs vont s’adapter à un réseau qui évolue au cours du temps (ajout ou suppression de routes, panne d’un routeur, etc..). Pour cela les routeurs se transmettent des informations pour qu’ils puissent mettre à jour leur table de routage.
Pour chacune des videos, au cours de leur visionnage, prendre en notes pour repondre aux questions suivantes:
Le routage à vecteurs de distance
Video (Youtube): Mooc de l'INT (institut des Mines Télécom)
Les routage à états de liens
Video (Youtube): Mooc de l'INT (institut des Mines Télécom)
Pour le routage étudié, un routeur connait-il la carte globale du reseau (quel routeur est connecté à tel autre)?
Pour le routage étudié, s’agit-il des protocoles RIP ou OSPF?
communique t-il avec ses voisins directs, ou avec l’ensemble du reseau?
communique t-il aux autres routeurs de gros ou petits volumes d’informations pour établir sa table de routage?
un routeur, connait-il le chemin exact pour atteindre n’importe quel routeur du reseau?
connait-il le nombre de sauts pour atteindre n’importe quel routeur du reseau?
selectionne t-il le routeur voisin qui va donner le plus court chemin en nombre de saut / en durée d’acheminement? (Question de l’exercice n°4 du sujet de baccalaureat 2021, Polynesie)
Comment met-il à jour sa table de routage lorsqu’il y a une modification du reseau?
Routage à vecteur de distance
exemple de table de routage à vecteur de distance
Un vecteur de distance est une donnée constituée de (adresse du reseau, nombre de sauts, gateway)
Coût associé au chemin: Le nombre de sauts (routeurs traversés)
Exemple de protocole: Routing Information Protocol, RIP (basé sur l’algorithme de Bellman et Ford)
Mise à jour de la table de routage: Les routeurs envoient leur table de routage (complète ou non), aux routeurs voisins de façon périodique. Lorsque le routeur reçoit la table de routage du voisin, il met à jour sa table à partir de ces informations: pour chaque vecteur de distance donné par le routeur voisin, il incrémente la valeur du nombre de sauts d’une unité, et compare avec sa table:
Si le coût est inférieur à celui de sa propre table, ou s’il s’agit d’une nouvelle adresse, il remet celle-ci à jour en considérant ce nouveau chemin.
Si le coût de l’une de ses entrées dans la table semble augmenter, il peut aussi s’agir d’une modification du reseau (panne, route coupée…). Il met à jour le nouveau coût pour son vecteur de distance.
Ainsi, les informations vont circuler de proche en proche, très rapidement. Le routeur ne connait pas la route précise pour atteindre une adresse dans le reseau, mais la passerelle à prendre pour optimiser le coût du chemin (distance, ou métrique la plus petite).
Inconvenients de cette méthode:
il peut survenir des problèmes de convergence des données en cas de coupure d’une route sur le reseau (boucles, voir video). Le temps de convergence, même sans ce problème de boucle est relativement long. D’autant plus que le reseau est grand.
Il peut y avoir des itinéraires qui bouclent (voir video plus haut).
Protocole RIP: (Routing Information Protocol). Issu des travaux de Bellman-Ford (publiés en 1956 et 1958), il a été développé par l’université de Californie. Il est utilisé initialement pour ARPAnet, ce qui en fait son grand succès.
RIP utilise une métrique à nombre de sauts (hop en anglais, correspond au nombre de routeurs à traverser pour arriver à destination). Le nombre de sauts est limité à 15.
Chaque routeur envoie sa table de routage à ses voisins toutes les 30 secondes.
Si une route n’est pas actualisée pendant 180s, elle est supprimée de la table
Video (Youtube): simulateur RIPLAY
Routage à états de liens
exemple de table de routage à états de liens
Coût associé au chemin: homogène à une durée d’acheminement, calculé sur le débit des différentes sections du chemin. Dépend de l’encombrement, état du réseau, …
Exemple de protocole: Open Shortest Path First, OSPF: algorithme à état de liaison, basé sur la recherche du plus court chemin (Dijkstra).
Mise à jour de la table de routage: Le routeur envoie des petits messages, de type bonjour dans le reseau, et mesure la durée de reponse. Il construit un paquet spécial contenant les informations qu’il vient de découvrir, avant de la diffuser à tous les autres routeurs. Il établit ainsi une table avec, pour chaque adresse la mention d’une métrique qui depend du debit de chaque liaison, et déduit le plus court chemin vers chaque destination à partir de l’algorithme de Dijkstra. La métrique est obtenue en additionnant les coûts de chaque liaison.
Avantages:
Plus de problème de boucle puisque la mise à jour des routeurs se fait simultanément.
En théorie, pas de limitation de la taille du réseau.
Inconvénient : Les tables de routage croissent avec le nombre de routeurs dans un réseau. Ce qui nécessite plus de mémoire au sein des routeurs et plus de temps pour explorer les tables.
Exercice n°3 du sujet de baccalaureat Metropole-2 2022: représentations binaires et protocoles de routage. (RIP, OSPF), minimiser le nombre de routeurs à traverser pour une requête.
Le debit est la vitesse à laquelle sont échangées les données, expimée en bits/s (ou kb/s, Mb/s…). Le débit se définit par le rapport du nombre de données circulant (en bits), par la durée (s).
$$D = \tfrac{N}{s}$$
Pour assurer une navigation correcte sur Internet ou regarder la télé ou des vidéos en streaming, le debit minimum doit être de 8Mb/s.
En 2022, l’objectif est de fournir en france, à tous les foyers, le THD (très haut débit), soit 30Mb/s.
Avec la fibre, ce débit est encore dépassé (quelques centaines de Mb/s).
de nombreux sites proposent un test de debit pour votre connexion internet
Projet sur le hack ethique et le chiffrement RSA: Lien 4
Chiffrements symétriques
du chiffrement de Cesar à celui de la machine Enigma…
Vocabulaire
Chiffrer: transformer les caractères d’un texte pour le rendre incompréhensible, sauf pour celui qui possède la clé de chiffrement.
Déchiffrer: transformer le texte chiffré en texte clair à l’aide de la clé de chiffrement
Décrypter: transformer le texte chiffré en texte clair sans posséder la clé.
Cryptologie: science du secret: possède deux branches
cryptographie: étude de l’art du chiffrement
cryptanalyse: analyse des méthodes de chiffrement pour les casser (décrypter)
à quoi sert le chiffrement?
Le chiffrement a pour but de protéger nos données, nos communications, mais aussi de signer nos messages et de s’assurer que l’on communique bien avec la bonne personne:
Authentification: L’authentification est la procédure qui consiste, pour un système informatique, à vérifier l’identité d’une entité (personne, programme, machine).
L’intégrité des données désigne le fait que les données ne soient pas modifiées au cours d’une communication ou de leur stockage.
Ainsi, si vous envoyez un texte chiffré sur un canal non sécurisé, le texte chiffré pourra être intercepté et altéré par un attaquant avant d’atteindre son destinataire. Pour contrôler cette intégrité, on associe au message une valeur de contrôle.
La confidentialité: Le chiffrement permet de protéger la confidentialité de vos données à l’aide d’une clé secrète.
Chiffrement symétrique - definition
Le chiffrement symétrique utilise la même clé (ou la même table) pour chiffrer et déchiffrer le message. L’algorithme peut être connu par l’adversaire. Mais le secret repose sur celui de la clé.
Le chiffrement par décalage, ou chiffre de Caesar
Principe
Le chiffre de César fonctionne par décalage des lettres de l’alphabet.
Chiffrement par décalage - wikipedia
Cet algorithme de chiffrement utilise une fonction périodique pour transformer les rangs de chaque lettre:
La fonction utilisée est une fonction périodique, issue de l’arithmétique modulaire.
Compléter l’algorithme du chiffrement de César. On suppose qu’il existe une clé c correspondant au décalage utilisé. Le message clair est m et le message chiffré est m_chiffre
On peut utiliser les fonctions numero(l:str)->int et caractere(n:int)->str
monosubstitution par décalage ou par substitution: Une lettre du message clair va t-elle donner différentes lettres chiffrées, ou une seule?
Facilité du décryptage
Pour decrypter le message, on peut tester une à une toutes les clés, jusqu’à découvrir un message intelligible:
m_dechiffre = ""
pour chaque valeur i dans {0,25}:
pour chaque lettre l de m_chiffre:
l_dechiffre = ...
m_dechiffre = ...
Décryptage par FORCE BRUTE: Combien y-a-t-il de clés possibles à essayer pour celui qui réalise le décryptage? Conclure.
Substitution monoalphabetique utilisant une table
Le chiffrement par monosubstitution a été également utilisé par différentes méthodes utilisant une table.
Carré de Polybe - le mot « bonjour » est ainsi chiffré par le carré de Polybe :12 34 33 24 34 45 42 - wikipedia
Le code issu du carré de Polybe a été utilisé par les prisonniers, qui transmettaient leur message en tapant sur les murs
Tap code
Vous trouvez ces méthodes de chiffrement trop simpliste? Regardez alors sa déclinaison avec le
chiffrement de Playfair
VIDEO: chiffrement de Playfair - youtube - Astuces et tutoriels
Decryptage par analyse fréquentielle
Le problème avec ce type de chiffrement monoalphabetique, est qu’il est possible de repérer comment sont transformées certaines lettres à partir de l’analyse fréquentielle du message chiffré.
On peut alors utiliser la frequence des lettres pour dechiffrer et comparer avec la frequence moyenne dans une langue. (200 caracteres suffisent). Il y a aussi tout un tas de statistique, comme les lettres uniques, doubles lettres, finales, etc… C’est un marqueur suffisant pour savoir comment le code est fait.
frequence des lettres en français, calculée sur la lecture de plusieurs ouvrages classiques (10 millions de caracteres)
Cette analyse frequentielle est plus difficile (mais pas impossible) dans le cas du chiffrement de Playfair, car celui-ci utilise une methode de substitution d’un groupe de 2 lettres: c’est une substitution polyalphabetique. Le nombre de combinaisons possibles avec 2 lettres est alors de $26^2 = 676$.
Substitution polyalphabétique
Principe
Polyalphabetique: Se dit d’un chiffre où un groupe de n lettres est codé par un groupe de n symboles. Le chiffrement Playfair, vu plus haut s’apparente à une substitution polyalphabetique, puisqu’il substitue des digrammes (groupes de 2 lettres) dans le texte d’origine.
Contrairement aux chiffrements monoalphabetiques, qui sont des chiffrements par flot (caractères transformés un à un), les chiffrements polyalphabetiques réalisent un chiffrement par blocs (plusieurs caractères transformés en une fois).
L’exemple suivant montre une polysubstitution simple avec une clé de longueur 3 qui va décaler les lettres de l’alphabet :
On définit la clé ‘123’ qui indique que le premier caractère sera décalé d’une position, le second de 2 et le troisième de 3 positions, etc.
Le mot : WIKIPEDIA donne donc dans ce cas XKNJRHEKD.
Mais si on chiffre le mot : AAAAAAAAA cela donnera BCDBCDBCD. La lettre A ne donne pas toujours la même correspondance chiffrée.
Chiffrement de Vigenère:
Le chiffrement de Vigenère utilise ce principe de décalage à partir d’une clé exprimée par un mot.
image issue du site books.openedition.org
C’est souvent ce type de codage qui est proposé dans la litterature et le cinema.
affiche du film Benjamin Gates et le Tresor des Templiers
Décryptage
L’analyse des fréquences est moins pertinente lorsque le message a été chiffré avec un chiffrement polyalphabétique (qui tend à rendre aléatoire la fréquence des lettres).
Si on parvient à découvrir la périodicité, on peut en déduire la longueur de la clé. La connaissance de la longueur de la clé est essentielle pour pouvoir pratiquer l’analyse frequentielle: Une même lettre ne donne pas toujours le même caractère chiffré.
Le decryptage par force brute repose sur l’essai de toutes les clés possibles, par combinaison sur tous les caractères de la clé. Si celle-ci a une longueur n, cela va faire $X^n$, où X est la longueur de l’alphabet. C’est une fonction exponentielle.
La fonction de dechiffrage est alors executée un nombre de fois correspondant à $X^n$, dans le pire des cas.
Enigma: machine électromécanique portative servant au chiffrement et au déchiffrement - wikipedia
La machine utilise des rotors qui sont mis en position selon une clé. L’alphabet est chiffré selon la position initiale de ces rotors. Ceux-ci se décalent lors de l’utilisation.
Des branchements permettent d’ajouter des permutations des caractères.
Tout ceci modifie l’alphabet chiffré et augmente sérieusement la complexité.
Comme tout chiffrement symétrique, déchiffrer se fait avec la même machine, à condition d’utiliser la même clé.
Son utilisation la plus célèbre fut celle faite par l’Allemagne nazie, avant et pendant la Seconde Guerre mondiale, la machine étant réputée inviolable selon ses concepteurs.
Le principe de la machine Enigma était connu. Le concepteur savait à l’avance que certains modèles pourraient être volés par les alliés. Ce qui fit son efficacité, c’est le nombre immense de combinaisons possibles pour les réglages initiaux de la machine et le choix de la clef brute du message.
Question 1: Quelle clé a été utilisée pour chiffer ce texte (avec l’algorithme de César)?
$$jyfwavnyhwopl hwwspxbll$$
Question 2: Décrypter ce message.
Question 3: Proposer un programme en python qui chiffre un message clair m en un message codé selon la clé numérique c.
Aide:
La fonction ord('x') retourne un entier correspondant à la position d’un caractère dans la table ascii.
Par exemple, ord('A') retourne 65, ord('B') retourne 66,…
La fonction chr(N) retourne le caractère de rang N: chr(65) retourne ‘A’.
Substitution polyalphabétique: Chiffrement de Playfair
A partir des explications données dans la video:
Question 1: Construisez la matrice pour l’algorithme de Playfair avec la clé estienne.
Question 2: Chiffrer le message: ACTIONREACTION
Question 3: S’agit-il d’une méthode utilisant la substitution monoalphabetique, ou polyalphabetique?
Question 4: Avec cette méthode, le decryptage est-il possible par analyse fréquentielle?
Frequences des lettres dans un texte
La fonction suivante retourne une liste de 26 valeurs de type float, donnant dans l’ordre de l’alphabet, la frequence pour chaque lettre dans un texte:
deffreq(m):frequences=[0]*26n=len(m)forcinm:...
Question 1: Compléter le script de la fonction freq.
Question 2: L’un des 2 a été chiffré avec un algorithme de substitution mon-alphabetique, et l’autre, poly-alphabétique. Lequel est mono-alphabétique?
Question 3: Tracer un histogramme à partir du texte chiffré en mono-substitution. On donne un exemple de script ci-dessous pour réaliser le graphique:
importmatplotlib.pyplotaspltfig=plt.figure()ax=fig.add_axes([0,0,1,1])etiquettes=['a','b','c','d','e']valeurs=[23,17,35,29,12]# Affichage des donnéesax.bar(etiquettes,valeurs)plt.title("Histogramme")# Titre du graphiqueplt.ylabel('Nombre')# Titre de l'axe yplt.xlabel('alphabet')plt.show()# Affichage d'une courbe
Question 4: Peut-on utiliser la fonction XOR pour chiffrer PUIS dechiffrer un message, avec la MEME clé de chiffrement? Expliquer à partir de l’exemple ci-dessus.
Question 5: On s’interresse maintenant à la programmation de la fonction XOR pour chiffrer un message à partir d’un masque:
Le masque (correspond à la clé) aura une longueur inférieur au message. On utilise le masque selon la méthode de chiffrement polyalphabetique vue en cours.
Le chiffrement demande de faire correspondre les caractères avec des nombres entiers. On utilisera pour cela un alphabet de 32 caractères ($2^5$). Chaque lettre de l’alphabet correspondra alors à un nombre compris entre 0 et 31.
Question 6: Lorsque l’on place 2 entiers inférieurs à 32 dans la fonction XOR, celle-ci retourne un entier également inférieur à 32. Pourquoi? (Representer ces nombres en binaire, sur un octet, et verifier cette affirmation)
Question 7: Compléter la fonction chiffre(message, masque) qui chiffre message en le XORant avec masque.
Cette fonction doit pouvoir aussi servir à déchiffrer le message chiffré.
Projet sur le hack ethique et le chiffrement RSA: Lien 4
Chiffrements asymétriques
Pour le chiffrement symétrique, le seul secret, c’est la clé de chiffrement. Cette clé doit avoir, pour des raisons pratiques, une longueur raisonnable (64, 128, 256 bits). Ce chiffrement permet de communiquer de manière confidentielle, ou de préserver la confidentialité de nos données sur un disque dur.
L’un des inconvénients du chiffrement symétrique est le nombre de clés important qu’il faut par couple d’utilisateur, à l’echelle d’internet. De plus, comment assurer l’echange de clés entre participants de manière sûre?
L’autre problème avec le seul chiffrement symétrique, c’est qu’il ne permet pas de repondre aux besoins d’authentification (reconnaitre l’identité) et d’authenticité (le message n’a pas été modifié).
Pour comprendre ces termes, on utilise le scenario suivant. Alice et Bob sont 2 personnes qui veulent echanger des messages de manière sécurisée. Une 3e personne, appelée Trudy joue le rôle d’un attaquant.
Le trio Alice - Bob - Trudy
Le chiffrement asymétrique utilise plusieurs clés, une pour le chiffrement, et une autre pour le dechiffrement. Il repose sur des propriétés mathématiques de l’arithmetique modulaire. (voir principe du chiffrement RSA: wikipedia)
Principe du chiffrement RSA
Confidentialité
Il doit y avoir 2 clés. L’une de ces clés doit rester secrête, et conservée par l’expediteur du message: c’est la clé privée. L’autre clé utile pour le chiffrement et le dechiffrement est partagée: elle est dite publique. On peut indifféremment chiffrer avec la clé publique et déchiffrer avec celle privée, ou l’inverse.
VIDEO chiffrement asymetrique (demarrer à 4min28) - chaine ScienceEtonnante
Ainsi, comme la clé de Bob est publique, Alice peut utiliser cette clé pour chiffrer le message qu’elle veut lui envoyer, un peu comme si elle mettait le message dans un coffre (celui de Bob). Et Bob, qui possède la clé privée correspondante (la clé de son coffre) peut alors déchiffrer le message d’Alice.
Chiffrement asymetrique
Confidentialité:
Alice : C = chiffrement(m,Bob_public_key) => Bob
Puis, pour Bob:
m = dechiffrement(C,Bob_private_key)
Authentification
On peut utiliser cet algorithme pour authentifier l’auteur du message, et réaliser une signature numérique.
Imaginons que Bob utilise sa clé privée pour chiffrer un message M. Il l’envoie à Alice, qui, en utilisant la clé publique de Bob, pourra le déchiffrer. Elle pourra ainsi s’assurer que Bob en est bien à l’origine et que son contenu n’a pas été modifié.
En effet, comme il est le seul à posséder la clé privée, ce message M vient bien de Bob.
Compléter la situation où Bob envoie un message de type Bonjour à Alice, en utilisant sa clé privée:
Bonjour Alice - via chiffrement asymetrique
Le point faible de cet échange vient de la distribution de la clé publique entre Bob et Alice.
Cet échange n’est réellement sécurisé qu’à la condition que la clé publique de Bob, vienne bien de Bob. Et que personne ne se soit introduit dans la discussion pour substituer la clé publique de Bob par la sienne (attaque de l’homme du milieu).
Compléter la situation suivante où Eve réalise une attaque dite de l’homme du milieu. Elle envoie au préalable sa propre clé publique à Alice et Bob. Puis elle se fait passer pour chacun des 2 lors de la discussion.
Bonjour Alice, bonjour Bob - Eve
Authentification:
Bob : D = chiffrement(signature,Bob_private_key) => Alice
Puis pour Alice:
signature = dechiffrement(D,Bob_public_key)
Organismes de certification
Pour s’authentifier, Bob doit d’abord envoyer à Alice un certificat, qui contient sa clé publique mais aussi d’autres informations qui permettent de verifier la validité de ce certificat, en particulier l’emetteur: le nom de l’autorité de certification, une infrastructure à clé publique (PKI) qui a validé l’identité de Bob.
Certificats: Les navigateurs permettent d’ouvrir les pages des sites qui ont pu être authentifiés. Pour faire ceci, les navigateurs intègrent un certain nombre de certificats reconnus. Pour les autres, ils utilisent une chaine de certification: les navigateurs font confiance à certaines autorités de certification, qui ont au préalable, certifié leurs clients (possesseurs de sites web).
Si la chaine de confiance est rompue, votre navigateur affiche cette image qui va certainement vous dissuader de poursuivre votre navigation:
certificat non reconnu
En pratique, le certificat est un ensemble d’informations sur le propriétaire du domaine, la durée de validité, l’algorithme utilisé pour l’authentification, la clé publique, et surtout l’emetteur. Lorsqu’Alice reçoit le certificat que lui envoie Bob, elle consulte l’emetteur du certificat pour verifier qu’il s’agit bien du bon certificat, que celui-ci appartient bien à Bob.
procedure d'echange de certificat
Complément sur RSA (Grand Oral)
VIDEO - sciences etonnantes. L'Algorithme qui Sécurise Internet (entre autres...)
Alice veut envoyer un message à Bob
Elle doit d’abord lui envoyer sa clé publique:
Lors de la confection de la clé publique e, le propietaire de la clé utilise la valeur de 2 entiers p et qpremiers entre eux (secrets). En principe, p et q sont très grands (plus de 100 chiffres). Supposons pour l’exemple p=3 et q=11.
Le proprietaire calcule le module de chiffrementn=p*q. Ici, n=33. Ce calcul est très facile pour lui, alors qu’il est très difficile de trouver p et q en connaissant n. C’est sur cette difficulté que repose la robustesse de RSA.
Il calcule ensuite l’indicatrice d’Euler: f=(p-1)*(q-1) et détermine l’exposant public e qui doit être premier avec f.
Par exemple, ici, f=20. On peut choisir e=3,7,9,13,…
La couple (e,n) sera alors la clé publique d’Alice. Choisissons (3,33).
Bob reçoit la clé. Il l’utilise pour chiffre son message. Supposons que le message est le caractère F, le 6e caractère de l’alphabet. m=6. Alors le chiffrement se fait à l’aide de la relation: $m^e [n]$
En suivant l’exemple,
$$E(m) = 6^3 [33] = 18$$
Bob va alors transmettre 18, qui est le message chiffré.
Alice va alors déchiffrer le message avec sa clé privée.
Elle possède pour cela une clé constituée d’un exposant privé d qui est calculée comme inverse modulaire de e (modulo $(p-1).(q-1)$):
$$e.d = 1 + k\times(p-1)(q-1)$$
Pour dechiffrer le message M, elle fait: $M^d (mod n)$ où n=p.q
On exploite la propiété qui veut que $(M^e)^d = M (mod~n)$
Exemple:d=7 car $7 \times 3=21 = 20 + 1$, 7 est inverse modulaire de 3 modulo 20.
On a alors: $M^d [33] = 6$, Alice retrouve le message clair envoyé par Bob.
Avec les algorithmes classiques, casser la factorisation croit exponentiellement avec la longueur de la clé.
Principe d’une communication securisée HTTPS
Lors d’une communication HTTPS: les objectifs d’authentification, authenticité et de confidentialité sont remplis. Lors du protocole de communication, les chiffrements asymétriques et symétriques sont tous 2 utilisés:
Que Se Passe-t-il Entre un Navigateur Web (client) et un Serveur ?
le client demande au serveur que celui-ci s’authentifie (1)
Le serveur envoie au navigateur une copie de son certificat SSL (2)
Le navigateur vérifie s’il fait confiance à ce certificat SSL. Si oui,le client envoie de manière sécurisée une clé de session qui servira pour la communication (3). L’envoie de la clé se fait à l’aide du chiffrement asymétrique (RSA). Le client utilise la clé publique du serveur pour cet envoi.
Cette clé sera utilisée pour des chiffrements symétriques entre le client et le serveur (4).
établissement d'une communication securisée - OVH
Signature numérique: Lorsqu’on utilise sa propre clé privée pour envoyer un message, et qu’une autorité de certification peut garantir l’origine de cette clé privée, alors ce message envoyé a valeur de signature numérique. Il permet d’authentifier l’emetteur du message.
Fonction de hachage: intégrité
Une fonction de hachage est un algorithme qui prend en entrée une chaine de caractères de longueur quelconque, et qui retourne en sortie une chaine de caractères de longueur n fixée, appelée empreinte. Il est presque impossible de retrouver la chaine de caractères d’origine à partir de cette empreinte, tant la diffusion est importante suite à la modification d’une partie même infime du texte à chiffrer par cette méthode.
Une application classique de l’utilisation de la fonction de hachage est le stockage de mots de passe, ou bien la verification de l’intégrité d’un message envoyé (comme un checksum). Mais aussi pour la constitution d’une blockchain:
Dans la blockchain, chaque bloc contient le hash du bloc précédent, les données des nouvelles transactions, et le nouveau hash constitué à partir de ces données (hash du bloc precedent + transactions).
Blockchain
Une blockchain est un registre, une grande base de données qui a la particularité d’être partagée simultanément avec tous ses utilisateurs (constituant les noeuds d’un réseau distribué), tous également détenteurs de ce registre, et qui ont également tous la capacité d’y inscrire des données, selon des règles spécifiques fixées par un protocole informatique très bien sécurisé grâce à la cryptographie. Il est impossible d’effacer ou modifier ce qui a déjà été écrit dans ce registre. En pratique, une chaîne de blocs (blockchain) est une base de données qui contient l’historique de tous les échanges effectués entre ses utilisateurs depuis sa création.economie.gouv
La sécurité vient du consensus (PoW, Proof of Work) des validateurs lorsque de nouveaux ajouts sont proposés. La validation consiste en un calcul long et difficile sur les données de l’historique de la blockchain. Une fois qu’il y a consensus (un commun accord), un nouveau bloc est ajouté, et la base de données (la blockchain) est alors proposée à tous les noeuds du reseau. (mise à jour).
Cette tâche “ingrate” realisée par les validateurs est remunérée. Le bloc contient ainsi l’adresse de cryptomonnaies, qui sont partagées entre validateurs: Un registre distribué doit être accompagné d’une cryptomonnaie (propriétaire ou utilisée à partir d’un autre registre) afin de fournir des incitations pour maintenir opérationnels les programmes de validation et de synchronisation.
Pour résumer, une blockchain est un registre regroupant les transactions et adresses possédants des Bitcoins (ou autre cryptomonnaie), sécurisé par un protocole de validation par calcul et consensus.
La technologie “blockchain” s’est développée pour soutenir des transactions réalisées via les cryptomonnaies/crypto-actifs. Mais d’autres domaines et secteurs d’activités, marchands ou non marchands, publics ou privés, utilisent déjà la chaîne de blocs (blockchain) ou prévoient de le faire dans les années à venir: Dans le secteur de l’assurance par exemple, l’apport de la blockchain tient par exemple à l’automatisation des procédures de remboursement.
Il est possible de lire dans la blockchain. On utilise pour cela un explorateur de blocs.
video sciences etonnantes - blockchain
Il existe un autre type de validation, le PoS (Proof of Stake, ou preuve d’enjeu), qui permet d’augmenter grandement le flux de transactions. La blockchain Ethereum par exemple a effectué sa transition de la preuve de travail (PoW) vers une preuve d’enjeu (PoS) en septembre 2022. Pour participer à la sécurisation du réseau d’une blockchain PoS, il suffit d’avoir accumulé une quantité suffisante de jetons de la cryptomonnaie échangée sur le réseau. Plus une personne possédera de jetons d’une cryptomonnaie, plus on considérera que la sécurité du réseau est un enjeu important pour elle. Il y aura alors plus de chances d’être sélectionné (il y a une part d’aleatoire) pour produire un nouveau bloc et obtenir une récompense, en jetons.
Exercices
Nombre de clés:
Un groupe de n personnes souhaitent communiquer entre elles, chacune, deux à deux. Elles souhaitent utiliser un moyen de communication sécurisé par un chiffrement symétrique. Combien de clés différentes seront nécessaires?
Méthode de chiffrement de Vigenère.
Si on appliquait cette méthode à un alphabet de 95 caractères (les caractères ascii):
Combien de clés différentes peuvent exister avec 4 caractères?
Combien de temps cela prendrait-il au maximum pour déchiffrer un message par recherche exhaustive (force brute), si le temps de calcul pour le déchiffrement est de 1 milliseconde par clé?
Mots de passe
Combien de mots de passe différents de 10 caractères peuvent être générés à l’aide des 95 caractères ascii?
Avec un ordinateur capable de tester 1 million de mots de passe par seconde, combien de temps cela lui prendra t-il pour explorer l’ensemble des combinaisons?
Expliquer ce qu’est une attaque par recherche exhaustive.
Pour les proriétaires d’un site internet, vaut-il mieux conserver dans la base de données, les mots de passe des clients, ou bien le hachage de chacun de ces mots de passe?
RSA
Quel est la valeur de $8^7$ modulo 40?
Verifier que 55 est decomposable en produit de 2 nombres premiers p et q. Calculer (p-1)*(q-1)
Soit la clé publique $e=3$. Quel est l’inverse de $e$ modulo 40? Appeler ce nombre $d$.
Chiffrer le message M = 5 avec la clé publique e, selon $M^e(mod~ 55)$
Dechiffrer $M^e(mod~ 55)$ avec la clé privée d, selon la même fonction que précédemment.
Dans un protocole de chiffement asymétrique, les algorithmes de chiffrement et de déchiffrement sont-ils les mêmes?
Dans un protocole de chiffrement asymétrique, toutes les personnes possédant la clé publique de Bob peuvent lui envoyer un message?
Dans un protocole d’authentification, toutes les personnes possédant la clé publique de Bob peuvent vérifier sa signature émise?
Supposons que Bob envoie à Alice un message chiffré de la manière suivante: C = chiffrement(m,Bob_public_key). Est-ce qu’Alice peut authentifier Bob avec ce message?
Supposons que Bob envoie à Alice un message chiffré de la manière suivante: C = chiffrement(m,Bob_private_key). Est-ce que ce message est confidentiel?
Ce TP a été vu en 1ere NSI à la seance suivante.
On cherche à créer un système de 2 sous-réseaux locaux. Ces reseaux auront pour adresses: 198.168.0.0 et 192.168.2.0
C’est à dire que toutes les machines du réseau 198.168.0.0 auront en commun les 3 octets 198.168.0 et toutes les machines du reseau 198.168.2.0 auront en commun les octets 198.168.2.
Le sous-réseau 192.168.0.0 comportera un switch et 3 ordinateurs M1, M2 et M3. Ces machines auront pour adresses IP:
192.168.0.1
192.168.0.2
192.168.0.3
Le sous-réseau 192.168.2.0 comportera un switch et 3 ordinateurs M4, M5 et M6. Ces machines auront pour adresses IP:
192.168.2.1
192.168.2.2
192.168.2.3
Votre système devrait ressembler à l’image suivante:
systeme de 2 sous-reseaux sans routeur
Tester alors la commande ping depuis la machine M1 vers celle M6 du 2e sous-reseau.
Installer les logiciels utiles sur les machine M1 et M6 pour faire communiquer les machines. Pour faire cela: Démarrer la simulation:
Puis faire un double clic sur chacune des machines, et installer le logiciel ligne de commandes.
console d'installation de logiciels
tester alors les commandes suivantes depuis la machine M1:
ipconfig : vérifier la correspondance de l’adresse IP de la machine M1
ping 192.168.0.2 : pour établir et tester une connexion avec la machine M2
traceroute 192.168.0.2 : pour établir le trajet qui mène jusqu’à M2
Tester alors les commandes ping et traceroute vers une adresse de machine inexistante dans le réseau. Par exemple 192.168.0.4
Qu.1a: Quels messages indiquent que la communication M1->M2 est possible, alors que M1-> 192.168.0.4 ne l’est pas?
Qu.1b: La machine M6 est-elle accessible depuis M1? Pourquoi?
Vous constatez que l’accès à M6 n’est pas possible. En effet, votre système doit disposer d’un routeur, une machine capable de faire interface entre 2 reseaux…
Modifier le système en ajoutant un routeur:
clic droit sur le Switch2 : faire supprimer tous les cables
ajouter le routeur
paramétrer le routeur:
clic sur le routeur
renseigner les adresses des 2 reseaux sur l’interface du routeur:
192.168.0.254 du côté du reseau 192.168.0.0 (à gauche)
192.168.2.254 du côté du reseau 192.168.2.0 (à droite)
adresses des reseaux
cocher routage automatique:
option routage automatique
Pour chacun des ordinateurs du sous-reseau 1, M1, M2, M3, renseigner l’adresse de l’interface reseau 1 du routeur: mettre 192.168.0.254 dans le champs passerelle. Ce sera l’adresse IP de la carte reseau du routeur, du côté du reseau 192.168.0.0 (on met 254 à la place de 0 pour l’adresse routeur).
renseigner l'adresse reseau pour chaque ordinateur
Même travail pour M4, M5, M6: renseigner la passerelle 192.168.2.254
refaire le cablage
Qu.1c: Pourquoi le routeur de votre système informatique possède t-il 2 adresses IP?
Qu.1d: Démarrer le système et tester alors la commande ping de M1 vers M6, puis de M6 vers M1. Que constatez-vous? Pourquoi?
Simulation d’un reseau avec Filius (version term NSI): Routage statique
1. Avec le logiciel Filius, construire les réseaux ci-dessous :
système 2
2. Vous devrez renseigner les adresses IP des machines, ainsi que les masques de sous-reseau.
Tester avec un ping si un ordinateur du réseau R1 peut communiquer avec un autre ordinateur du réseau R1. Conclure.
Tester avec un ping si un ordinateur du réseau R1 peut communiquer avec un autre ordinateur du réseau R2. Conclure.
Remarque : Toutes les machines appartenant au même réseau devront posséder la même adresse réseau sinon elles ne pourront pas communiquer ensemble, même si elles sont bien physiquement reliées.
3.Ne pas utiliser le routage automatique. Compléter les adresses IP des passerelles. Tester à nouveau avec un ping si un ordinateur du réseau R1 peut communiquer avec un autre ordinateur du réseau R2. Puis avec avec un ordinateur du réseau R3. Conclure.
4. Mettre en place le réseau R4. (Adresse IP et passerelle). Tester avec un ping si un ordinateur du réseau R1 peut communiquer avec un ordinateur du réseau R3.
5. Comment modifier la table de routage du routeur A ?
6. Comment modifier est la table de routage du routeur G ?
Aide pour renseigner la table de routage
On cherche à renseigner pour le routeur A la route à prendre pour acheminer un paquet vers le reseau 192.168.4.0
exemple de systeme à 2 routeurs
Dans la table de routage du routeur A, il faudra ajouter une nouvelle entrée, et renseigner la passerelle pour rejoindre ce reseau éloigné:
exemple de nouvelle entrée dans la table de routage du routeur A
Alors, à condition de renseigner également le routeur B, avec la passerelle vers le reseau 192.168.0.0, les ordinateurs des 2 reseaux devraient communiquer ensemble.
exemple de nouvelle entrée dans la table de routage du routeur B
Une base de données est une collection de données qui vont être partagées entre plusieurs services, serveurs, utilisateurs.
Le modèle entité-association
La première étape pour aboutir à un modèle permettant de stocker les données dans une base consiste à identifier les objets et définir leurs liens.
Cette modélisation repose sur des principes mathématiques mis en avant par E.F. Codd (1923 - 2003, un informaticien britannique), et c’est cette modélisation qui est implémentée dans les bases de données.
Entité
on désigne par entité tout objet identifiable et pertinent pour l’application. Par exemple, pour la base de donnée précédente, les entités sont:
Films: les films
Réalisateurs: les réalisateurs
Pour chacune des entités, les individus ou objets ont en commun les même propriétés. Ce sont des tables, aussi appelées relations.
Attributs
Les entités sont caractérisées par des propriétés appelées attributs. Un attribut est désigné par un nom et prend ses valeurs dans un domaine énumérable. (notion à rapprocher du type en Python).
On exprime ici chaque attribut par son couple nom: domaine (domaine = type). Ces attributs doivent être insécables, ce qui empêche d’en choisir un du genre adresse (qui se decomposerait alors en n° + rue + ville).
Pour l’entité Films, ces attributs sont Titre et Annee.
Domaines
Les valeurs mises dans une cellule sont élémentaires. Il ne peut s’agir de types construits comme des listes.
INT ou INTEGER : un entier
FLOAT(x) : un nombre décimal avec x définissant la précision (nombre de bits de codage de la mantisse)
REAL est un synonyme standard de FLOAT(24)
CHAR(n) : chaine d’au plus n caractères
VARCHAR(n)
DATE une date
Association
Une association représente un lien entre les entités.
Il y a un lien représenté par le verbea réalisé entre les entités Réalisateurs et Films.
On distingue:
L’association binaire fonctionnelle: chaque occurence de l’entité A est liée à au plus une occurence de l’entité B. C’est équivalent à dire A=>B (la connaissance de A détermine celle de B). Dans ce cas, c’est la table A qui possède un attribut FOREIGN KEY qui pointe vers un attribut clé primaire de la table B.
association binaire fonctionnelle
L’association non fonctionnelle: Une occurence de A peut être liée à plus d’une occurence de B.
association binaire NON fonctionnelle
Vocabulaire employé dans le domaine des bases de données
Voici l’ensemble des mots utilisés, avec leur correspondance
Terme du modèle
Terme de la représentation par table
Relation
Table
n-uplet
ligne
Nom d’attribut
Nom de colonne
Valeur d’attribut
Cellule
Domaine
Type
La structuration des données
Clé (ou identifiant)
Une clé est un attribut d’une relation.
clé primaire : une clé conçue pour identifier de manière unique les éléments d’une table. Si un attribut est considéré comme clef primaire, on ne doit pas trouver dans toute la relation 2 fois la même valeur pour cet attribut.
Dans la situation fréquente où on a du mal à déterminer quelle est la clé d’un type d’entité ; on crée un identifiant abstrait appelé id (un numéro séquentiel) indépendant de tous les autres attributs.
Dans une table, l’un des attributs peut être la clé primaire d’une autre table. Il s’agit alors d’une clé étrangère. Cet attribut permet de faire reference à un enregistrement dans une autre table, et caractérise parfaitement cette autre entité.
Exemple:idMES est la clé étrangère dans la relation Films:
Titre
Annee
idMES
Hana-bi
1997
1
Big fish
2003
2
Edward aux mains d’argent
1990
2
La relation Réalisateur:
idMES
NomMES
PrenomMES
AnneeNaiss
1
Kitano
Takeshi
1947
2
Burton
Tim
1958
3
Tarantino
Quentin
1963
La base de données doit se conformer aux contraintes d’intégrité référentielles:
Contraintes d’intégrité
Une contrainte d’intégrité est une règle qui définit la cohérence d’une donnée ou d’un ensemble de données de la BD.
Les contraintes d’intégrité liées aux clés primaires et étrangères sont:
Contrainte de relation: chaque relation doit comporter une clé primaire.
Clé etrangère: traduit une association. Elle doit être la clé primaire de l’autre relation à laquelle elle se réfère. Cette autre relation doit contenir l’élément auquel on veut se référencer AVANT de faire référence.
Modification: on ne doit pas faire de modification de la clé primaire d’une occurence si celle-ci est liée.
En pratique, ces contraintes sont définies au moment de la création d’une table.
PRIMARY KEY : contrainte de clé primaire. Définit l’attribut comme la clé primaire
FOREIGN KEY : contrainte de clef étrangère. Assure l’intégrité de référence. Cette clé étrangère n’est pas primaire pour la relation étudiée mais elle est la clé primaire d’une autre relation.
En option, on peut ajouter des contraintes d’unicité ou de validité avec UNIQUE ou CHECK, ou autres:
NOT NULL: contrainte d’obligation de valeur. Les éléments de la colonne doivent forcément être renseignés
UNIQUE : la contrainte d’unicité, permet de s’assurer qu’une autre clef
pourrait remplacer la clef primaire: interdit que deux tuples de la relation aient la même valeur pour l’attribut.
REFERENCES nom table (`nom colonne) : contrôle l’intégrité référentielle entre l’attribut de la table et ses colonnes spécifiées
CHECK (condition) : contrainte de validation. Il s’agit d’une assertion, qui contrôle la validité de la valeur de l’attribut spécifié dans la condition. Permet de restreindre les valeurs de la-les colonnes qui la-les composent.
D’après la règle énoncée sur la contrainte de clé étrangère, la table LIVRES doit être créée APRES celle AUTEURS (à cause de la contrainte REFERENCES):
Une relation possède un nom, et se compose de colonnes désignées par un nom d’attribut avec des valeurs d’un certain domaine.
Le schéma d’une relation: peut être représenté par un diagramme (une table), donnant les noms des relations, les attributs, leur domaine, et la mention de la clé primaire. Mais on préfère donner ce schéma sous forme d’un ensemble de tuples: $S = ((A_1,domaine_1, (A_2,domaine_2) ...(A_n,domaine_n))$ où les $A_i$ sont les attributs.
Lorsqu’une base de données comporte plusieurs tables, l’ensemble des schémas de ces relations s’appelle le schéma relationnel de la base de données.
Donner le schéma relationnel: Un schéma relationnel est un diagramme. On y représente les noms des relations, les attributs, leur domaine, les clés primaires soulignées et les clés étrangères précédées d’un # dans des tableaux, puis faire une flèche pour indiquer de quelle table la clé étrangère est la clé primaire.
schéma relationnel de la base de données définie plus haut sur les Films et Réalisateurs de cinéma:
schéma relationnel de la base de données films-realisateurs, base de libreoffice
Le degré d’une relation est le nombre d’attributs (ou de colonnes) et le cardinal d’une relation est le nombre de tuples (ou de lignes).
Le schéma d’une relation: peut être représenté par un diagramme (une table), donnant les noms des relations, les attributs, leur domaine, et la mention de la clé primaire. Mais on peut aussi donner ce schéma sous forme d’un ensemble de tuples: $S = ((A_1,domaine_1, (A_2,domaine_2) ...(A_n,domaine_n))$ où les $A_i$ sont les attributs.
Exemple: le schéma de la relation Films est: $$Film((Titre,str),(Annee,int))$$
Une table R, ou relation est un ensemble fini de n-uplets $(x_1, x_2, ... x_n)$ où les xi prennent leurs valeurs dans Ai.
Une occurence (ou élément d’une table R) est une ligne dans un tableau. On l’appelle aussi un enregistrement, ou un n-uplet.
Lorsqu’une base de données comporte plusieurs tables, l’ensemble des schémas de ces relations s’appelle le schéma relationnel de la base de données.
Donner le schéma relationnel: Une relation est un objet abstrait, on peut la représenter de différentes manières. Une représentation naturelle est le graphe entre les entités, représentant les relations et les associations.
Une association binaire entre les entités $E_1$ et $E_2$ est un ensemble de couples ($e_1$, $e_2$) avec $e_1$∈$E_1$ et $e_2$∈$E_2$.
Cette association peut être représentée à l’aide d’une clé etrangère, ou peut necessiter la création d’une nouvelle relation (et donc d’un nouveau tableau) pour répondre aux contraintes d’intégrité.
Règles de conception d’une base de données
Unicité: Toute entité donne lieu à une table dont la clé primaire est l’identifiant de l’entité.
Toute association binaire fonctionnelle est implémentée par la presence d’une clé étrangère dans la table, qui représente l’entité origine de la dépendance fonctionnelle.
Normalisation: Toute association non fonctionnelle génère une nouvelle table dont la clé primaire est l’ensemble des clés primaires des tables qu’elle relie. Un exemple d’association non fonctionnelle, c’est lorsqu’une information apparait plusieurs fois, et necessiterait de modifier plusieurs lignes s’il fallait effectuer un changement.
Remarque:la clé d’une association (binaire) entre une entité E1 et une entité E2 est le couple constitué de la clé e1 de E1 et de la clé e2 de E2.
langage SQL
Langage SQL
SQL: structured query langage = langage de requêtes structuré est un langage informatique de dialogue avec une base de données relationnelle (un fichier qui organise les données sur une ou plusieurs tables).
Une requête est une question posée à une base de données. Nous allons voir comment sont écrites les requêtes de base en SQL. Une requête est la traduction d’une relation écrite en algèbre relationnelle.
L’algèbre relationnelle est un outil créé par le chercheur E. Codd (1970) pour manipuler les tables dans le modèle relationnel. Ses principales opérations sont: SELECTIONNER certaines colonnes (Projection) ou certaines lignes (selection) d’une table, mais aussi de combiner 2 tables.
Chaque opération SQL prend en entrée une ou plusieurs tables et renvoie une table.
version pdf
Voyons dans un premier temps les requêtes utiles pour CREER, SUPPRIMER, REMPLIR et MODIFIER la table
CREATE TABLE va permettre d’indiquer le schéma d’une relation, avec ses Attributs et Domaines. Les types (ou domaines) les plus courants sont parmi:
INTEGER, entier positif ou nul
TEXT, CHAR(n), chaine de caractères
DATE, format de date du type YYYY-MM-DD
REAL, une valeur décimale
On peut ajouter des contraintes (constraints) en paramètre : PK (Primary Key), UNIQUE (dans une colonne, les valeurs doivent être uniques à chaque ligne), AUTOINCREMENT, NOT NULL (doit comprendre une valeur), DEFAULT ‘Not Applicable’ (la valeur mise par défaut si vide).
Les mots-clefs SELECT, FROM, WHERE, GROUP BY, HAVING et ORDER BY sont appelés des clauses.
clauses SQL sur la tables des romans
SELECT <attributs> FROM nom_table
SELECT est la commande qui retourne la table selon les attributs choisis. Il s’agit d’une Projection comme type d’opération relationnelle.
Une projection est un type de sélection où seulement une partie des attributs des tables choisies est retenue pour le résultat.
FROM est la table concernée.
Pour avoir toutes les colonnes, faire:
SELECT*FROMTable_notes
ou bien seulement certaines:
SELECTMath,Nom_eleveASNomFROMTable_notes
On peut renommer une colonne avec l’alias AS, et choisir un nom plus pratique.
SELECT DISTINCT retourne les éléments de manière unique.
Et limiter le nombre de lignes à 10 par exemple:
SELECT*FROMTable_notesLIMIT10
SELECT DISTINCT <attributs> FROM nom_table
L’ajout du mot-clé DISTINCT, ne va retourner qu’une seule fois les lignes pour chaque valeur d’une colonne donnée. Il n’y aura pas de doublon, seule la première occurence est retournée.
WHERE <condition>
La clause WHERE permet de SELECTIONNER des lignes à partir de conditions dans les requêtes, mais aussi de realiser des JOINTURES (voir plus loin)
Exercice: Représenter la table Table_notes (En-tête et contenu de la colonne) qui sera retournée par cette requête.
AVG SUM MIN MAX COUNT
Ce sont des fonctions d’agregation, qui retournent un resultat évalué sur la colonne issue de la SELECTION
Exemple1: Combien d’élèves ont plus de 15 en math dans la table Table_notes?
SELECT COUNT(*) FROM Table_notes WHERE Math > 15
Exemple2: Combien de romans de l’auteur id_auteur =5 y-a-t-il dans la table romans?
SELECTcount(*)FROMromansWHEREid_auteur=5
COUNT(*) va compter le nombre de lignes pour la selection donnée
SUM(attribut) va faire la somme pour les valeurs de l’attribut et pour la selection donnée
AVG(attribut) calcule la moyenne
MIN(attribut) retourne la valeur min, MAX(attribut) la vakeur max
Exercice: Ecrire la requête qui calcule la moyenne de math pour tous les élèves de la table Table_notes
GROUP BY <uneTable.attribut1>
Permet de regrouper des lignes les unes avec les autres.
Pour regrouper des lignes d’une table selon un attribut, il faut que ces lignes aient la même valeur pour cet attribut.
GROUP BY s’utilise avec des agrégats.
Exemple: Quel total de notes figure dans la table romanspour chaque auteur?
SELECTSUM(note)FROMromansGROUPBYid_auteur
Exercice: Ecrire une requête qui calcule la moyenne des notes obtenues par écrivain sur la table Romans.
ORDER BY <colonne> ASC [DESC]
Trions les lignes par ordre croissant des notes en math:
SELECTNom,MathFROMTable_notesORDERBYMathASC;
Sinon par ordre descendant: ORDER BY Math DESC
Exercice: Représenter le tableau retourné par la requête écrite en exemple.
Exercice: Ecrire une requête qui calcule la moyenne des notes obtenues par écrivain sur la table Romans et qui classe ces auteurs par ordre de note moyenne décroissante.
Remarque: On peut aussi rajouter une clause sur le nombre de lignes retournées avec LIMIT <nombre> Très pratiques pour de grandes tables.
‘GROUP BY … HAVING`
La clause HAVING permet d’effectuer une selection sur des valeurs issues de regroupements.
WHERE <colonne> LIKE <motif> et WHERE <colonne> IN <tuple>
LIKE
On peut faire une recherche dans une table selon certains motifs. Pour cela, on utilise WHERE ... LIKE <suivi de caractères spéciaux>.
Caractères spéciaux:
le caractère % représente 0, 1 ou plus de caractères
%s permet d’obtenir toutes chaines qui finissent par s, mais aussi le caractère unique s.
le caractère _ représente un caractère unique
ro_e permet d’obtenir robe ou bien rose
Exercice: Dans la relation Eleves de schéma `((prenom, TEXT), (nom, TEXT), (nais, DATE), (rue, TEXT), (numero, INTEGER), (CP, INTEGER), (ville, TEXT), (email, TEXT)):
Définir une requête qui permet d’obtenir tous les élèves nés en 2002
Définir une requête qui permet d’obtenir tous les élèves habitant dans le département des Alpes Maritimes.
Définir une requête qui permet d’obtenir tous les élèves ayant un compte e-mail chez l’opérateur laposte (du type pseudo@laposte.net)
IN
Pour faire une recherche dans une table selon une liste de critères, on utilise le mot clé IN
On peut par exemple rechercher les élèves qui habitent Nice, Saint-Laurent ou Cagnes-sur-mer dans la table Eleves:
Ecrire une requête sur la table Eleves qui retourne les noms des élèves dont la famille habite dans les départements (‘06’, ‘83’, ‘05’)
Jointure
Pour eviter les redondances, on a vu qu’il était préférable de répartir les données sur plusieurs tables, chaque table modélisant UNE seule entité.
La jointure permet de mettre en relation plusieurs tables, par l’intermédiaire des liens qui existent en particuler entre la clé primaire de l’une et la clé étrangère de l’autre.
La jointure est une opération de sélection car elle permet de ne retenir que les enregistrements pour lesquels la valeur de la clé primaire d’une table correspond à la valeur de la clé étrangère d’une autre table.
à la 4e ligne : on declare comment les 2 tables sont combinées : on veut faire correspondre la colonne ìd_customersde la table orders avec celle ìd_customersde la table customers.
Comme le nom d’une colonne va se retrouver dans de nombreuses tables, on utilisera la syntaxe : table_name.column_name
Se rendre à la page de Quentin Fortier, professeur en classes preparatoires https://sql-exercices.github.io/ et choisir (à gauche), l’exercice sur le métro parisien. Celui-ci propose de travailler sur une base de données à une seule table.
La page se présente comme ceci.
credit: fortierq Quentin Fortier
Pour chacune des questions, placer vos requêtes en bas de la page, et vérifier avec le bouton VALIDER.
TP2 sur la table des prenoms
Télécharger la table en format csv
Le site de l’insee propose une page avec les fichiers des prenoms de l’état civil: Lien
Un
fichier d’extension .sql a été généré à partir de ces données. Téléchargez le
ici.
Ouverture du fichier: Deux options possibles
Local: DB Browser for Sqlite
Lancez votre gestionnaire de base de données (DB Browser for Sqlite). Si besoin, une version portable se trouve ici
Dans le menu: Import: Database from SQL file…
Ouvrir le fichier qui se trouve dans vos Documents.
Le logiciel vous demande alors quel sera le nom de la base de données. Choisir: prenoms.
Pour la suite, les instructions seront données pour le logiciel en local: DB Browser for Sqlite.
Dans la partie supérieure gauche, observez 4 onglets qui permettent de choisir entre:
Database Structure
Browse Data
Edit Pragmas
Execute SQL
Choisir Database structure: nom de la table et des différents attributs
présentation des différentes tables et attributs
Choisir Browse Data: observer le contenu e la table
parcourir les valeurs de la table
Choisir Execute SQL
La fenêtre permet alors de placer une requete en langage SQLite. Le résultat dans une autre fenêtre, juste au dessous.
Afficher les premières lignes de la table afin de prendre connaissance des étiquettes des colonnes:
SELECT*FROMprenomsLIMIT10;
Executer avec le bouton d’execution.
Travail
Ecrire et tester une à une les instructions qui permettent de:
Afficher les dix premières lignes de la table
Afficher les lignes correspondant à l’année 2000. Là encore, mieux vaut ne demander que les 10 premières lignes…
Afficher les prénoms des garçons nés en 2000 (limiter à 50).
Combien de fois le prénom Nicolas a-t-il été donné en 2000 ?
Afficher les 10 prénoms de fille les plus donnés en 2000 rangés dans l’ordre décroissant du nombre de fois où ils ont été donnés. Utiliser les mots-clés:
SELECT FROM WHERE ORDER BY DESC LIMIT
Afficher les lignes des prénoms de garçons donnés entre 2000 et 2020 (inclus l’un et l’autre). Utiliser un AND pour tester l’encadrement des années.
Afficher le nombre de prénoms différents de garçons donnés depuis 2000.
SELECT COUNT(*) FROM WHERE
Afficher le nombre de naissances de garçons observées en 2020.
Afficher le nombre de filles et le nombre de garçons apparaissant dans la table.
SELECT SUM(nombre) FROM GROUP BY
Quel est le prénom, pour un certain sexe, en distinguant par exemple “Camille (fille)” et “Camille (garçon)”, qui a été le plus donné durant une année donnée ? En quelle année ?
SELECT FROM ORDER BY DESC LIMIT
En quelle année y-a-t-il eu le plus de naissances ?
SELECT SUM(nombre) FROM GROUP BY ORDER BY DESC LIMIT
Quels sont les 10 prénoms les plus donnés en France au cours du XXI-ème siècle en cours?
SELECT SUM(nombre) FROM GROUP BY ORDER BY DESC LIMIT
Autres travaux pratiques SQL
Table unique
Exercice sur les nouilles japonaises. Interface en ligne par N. Revéret sur forge.apps.education.fr
Pays, villes et langues parlées, plusieurs tables
Exercice sur le langage SQL rédigés par N. Revéret sur forge.apps.education.fr. Interface en ligne.
INSERTINTOLIVRES(id,titre,id_auteur,ann_publi,note)VALUES(1,'1984',1,1949,10),(2,'Dune',2,1965,8),(3,'Fondation',3,1951,9),(4,'Le meilleur des mondes',4,1931,7),(5,'Fahrenheit 451',5,1953,7),(6,'Ubik',6,1969,9),(7,'Chroniques martiennes',5,1950,8),(8,'La nuit des temps',7,1968,7),(9,'Blade Runner',6,1968,8),(10,'Les Robots',3,1950,9),(11,'La Planète des singes',8,1963,8),(12,'Ravage',7,1943,8),(13,'Le Maître du Haut Château',6,1962,8),(14,'Le monde des Ā',9,1945,7),(15,'La Fin de l’éternité',3,1955,8),(16,'De la Terre à la Lune',10,1865,10);
sauvegarder ;-)
Utiliser l’application SQLite (non installée sur PC du lycée)
La ligne de commande SQLite permet d’entrer deux types de commandes :
Les commandes spéciales pour la ligne de commande. Elles débutent toutes par un point (il ne faut pas qu’il y ait d’espace avant ni après le point pour que la commande fonctionne). Par exemple, .open, .show, .backup, .exit et toutes les autres commandes listées par .help. (voir la documentation SQLite ainsi que Command Line Shell For SQLite). Et la version windows
Les requêtes SQL, par exemple CREATE, SELECT, INSERT, UPDATE, DELETE. Chacune doit se terminer par un point-virgule.
Voici comment combiner ces deux types de commandes afin de vérifier la liste des tables de la base de données sélectionnée puis créer et afficher les enregistrements :
Pour démarrer sqlite, sous Windows, rechercher le fichier sqlite.exe
Dans la console: l’invite de commande commence alors par sqlite>
Les instructions suivantes permettent d’ouvrir et executer le fichier bibliotheque.sql, afficher les tables, puis fermer (si besoin) l’application sqlite:
lorsque vous écrivez select *, le retour à la ligne n’execute pas le script, mais attend la fin de l’instruction, jusqu’au point virgule ; final.
les requêtes et instructions SQL peuvent être écrites directement dans l’application sqlite, comme dans le fichier d’extension .sql. Il faudra alors le lire dans la console avec .read <nom_du_fichier>.
La dernière requête utilise une instruction imbriquée, mise entre parenthèses de la clause WHERE id=(SELECT ...)
l’instruction DELETE FROM LIVRES permet de supprimer tous les n-uplets de la table, mais pas de remettre à zero le compteur. Pour une remise à zero du compteur, il faut aussi effacer le seul élément de la table sqlite_sequence, créée dans la base de donnée en même temps que la première table.
SELECT … WHERE
Selectionner une partie de la table, en nommant les attributs:
Voici un scénario possible de fonctionnement de cette application :
L’application demande à l’utilisateur : « Quelle est la ville de départ ? ».
L’utilisateur répond « Caussade ».
L’application demande à l’utilisateur : « Quelle est la ville d’arrivée ? ».
L’utilisateur répond « Brive-la-Gaillarde ».
L’application envoie au SGBD la requête SQL :
SELECT heureDep, heureArr FROM trains
WHERE villeDep = ’Caussade’ AND villeArr = ’Brive-la-Gaillarde’;
Le SGBD répond au programme en envoyant l’ensemble de tuples {(15h47, 17h22); (18h21, 19h58)}
Le programme affiche à l’utilisateur : Résultats pour le trajet Caussade -> Brive-la-Gaillarde
Premier train : 15h47 -> 17h22
Second train : 18h21 -> 19h58
Ce scenario semble plausible. En réalité, nous verrons qu’il y a une couche intermédiaire de plus: l’application web, côté serveur.
Architecture Client-Serveur Web
Le serveur et ses clients sont des applications distinctes qui s’échangent des informations. Lorsque la connexion est établie, l’application cliente peut interroger le serveur en lui envoyant une requête (une instruction).
Il s’agit par exemple de demander une page web. Mais il peut aussi s’agir d’un besoin de services mettant en jeu la lecture, suppression ou modification d’une information dans une base de données.
Le serveur exécute alors la requête en recherchant les données correspondantes dans la base, puis il expédie en retour une certaine réponse au client. Il compose la page web avant de la distribuer au client s’il s’agissait d’un protocole http.
La communication entre le client et le serveur est donc faite de requêtes et de réponses.
client - serveur
Un serveur web est une application qui s’execute sur une machine et qui ecoute un port specifique.
Une application web est un programme stocké sur un serveur distant auquel on accede via une connexion au reseau, via http. Celui-ci peut faire interface avec une base de données, fabrique les pages web à la volée pour le client. Ce client a besoin d’un navigateur pour se connecter à cette application web. L’application web utilise comme langage de programmation un langage dédié, comme Python, PHP, node, C, ou autre.
Alors que la ressource côté client est, elle, programmée en HTML, Javascript, et CSS.
Qu'est ce qu'une application web - video de la chaine WayToLearnX
Un exemple de page statique
Le fichier suivant, formulaire.txt génère un formulaire. Lorsque l’on appuie sur le bouton, les valeurs des champs nom et pass sont transmises par methode POST.
exemple de page statique
Mais ici, ces valeurs ne peuvent pas être récupérées. Cela nécessiterait un script écrit en langage serveur. (voir plus haut).
Vous pouvez ouvrir ce fichier en le télechargeant dans vos documents, puis:
changer l’extension .txt => .html
ouvrir avec votre navigateur web
Serveur Python
Librairie http.server
Il est possible d’écrire en Python une application web. Le plus simple est d’utiliser les librairies http.server et cgi, directement intégrées au langage.
Une fois le script server.py lancé, le client pourra se connecter au serveur local à l’adresse http://localhost:8800.
Pour lancer votre serveur local, télécharger, et mettre dans vos documents le fichier server.py, puis executer à partir d’un IDE comme Spyder par exemple.
Librairie cgi
L’utilisation d’un formulaire ou la création de pages web dynamique nécessite d’importer la librairie cgi.
Les instructions de création de la page web seront mises dans un fichier d’extension .py.
Pour que le serveur compile et exécute le code source de votre fichier.py, il faudra naviguer vers ce fichier grâce à l’URL http://localhost:8800/fichier.py.
Dans ce fichier, CGI permet de générer des pages web sur le champ, en fonction des actions du client. (Par exemple le chargement du formulaire lors de l’appui sur le bouton).
Il suffira d’utiliser la fonction print pour afficher les éléments HTML dans la page du client.
A vous de tester: Dans un fichier que vous nommerez store.py:
Mettre les lignes suivantes dans le fichier:
# coding: utf-8#! /usr/bin/pythonimportcgiimportcgitbimporthtmlcgitb.enable()form=cgi.FieldStorage()print("Content-type: text/html; charset=utf-8\n")titre_formulaire="<h2>Entrez les identifiants des clients</h2>"titre_table="<h2>Table clients</h2>"html1="""
"""html2="""
"""html3="""
"""print(html1)print(titre_formulaire)print(html2)print(titre_table)print(html3)
Ajouter les instructions en HTML entre les guillemets affectés à html1, html2 et html3 (partager le script html en 3 parties).
Demander l’execution du script à l’aide du navigateur. Le formulaire affiché doit être identique à celui de la page formulaire.html précédent.
Python + SQL
Contenant son propre SGBDR intégré, Python dispose de manière native de la librairie sqlite3 au moment de l’écriture de ce TP. Il faudra importer ce module avec par exemple:
import sqlite3 as lite
Puis créer un objet-connexion vers la base de données clients.db, à l’aide de la fonction-fabrique connect():
con = lite.connect('clients.db')
Cet objet assurera l’interface entre votre programme et la base de données.
Pour dialoguer en SQL avec cet objet con, on utilisera encore un autre objet-interface que l’on appelle un curseur. Il s’agit d’une sorte de tampon mémoire intermédiaire, destiné à mémoriser temporairement les données en cours de traitement, ainsi que les opérations que vous effectuez sur elles, avant leur transfert définitif dans la base de données. Cette technique permet d’annuler et de revenir en arrière dans le traitement, sans que la base de données n’en soit affectée.
cur = con.cursor()
La requête est exprimée dans une chaîne de caractères, que nous transmettons au curseur par l’intermédiaire de sa méthode execute():
cur.execute("CREATE TABLE IF NOT EXISTS clients_login(id INTEGER, name TEXT, pass TEXT)")
Tant que le curseur reste ouvert, vous pouvez bien entendu ajouter des enregistrements supplémentaires :
cur.execute("INSERT INTO clients_login VALUES(1,?,?)",(nom,mdp))
Il sera souvent necessaire d’utiliser les contenus de variables python. Il est cependant fortement déconseillé de faire appel aux techniques ordinaires de formatage des chaînes, car cela peut ouvrir une faille de sécurité dans vos programmes, en y autorisant les intrusions par la méthode de piratage connue sous le nom de SQL injection. D’où la séquence d’instruction: VALUES(1,?,?)",(nom,mdp)).
Pour récuperer le contenu d’une table de la base de données: La méthode Fetchall (est )une alternative à Fetchone), permet de récupérer d’un coup l’ensemble du résultat d’une requête:
rows = cur.fetchall
La variable rows est alors une liste de listes. (les n-uplets de la table)
Le transfert dans la base de données sera déclenché par la méthode commit de l’objet connexion :
conn.commit()
A vous de jouer:
Ajouter la librairie sqlite3
Ajouter les lignes suivantes après avoir défini le Content-type du document client:
con=Nonecon=lite.connect('clients.db')withcon:cur=con.cursor()cur.execute("CREATE TABLE IF NOT EXISTS clients_login(id INTEGER, name TEXT, pass TEXT, PRIMARY KEY(id AUTOINCREMENT))")cur.execute("SELECT * FROM clients_login")rows=cur.fetchall()
Ajouter les instructions Python de lecture des champs du formulaire à l’aide de la fonction form.getvalue, ainsi que l’echange avec la base de données:
if(form.getvalue("name")!=None):nom=html.escape(form.getvalue("name"))mdp=html.escape(form.getvalue("pass"))withcon:cur=con.cursor()cur.execute("INSERT INTO clients_login (name,pass) VALUES(?,?)",(nom,mdp))con.commit()
Ajouter à l’interieur de cette structure conditionnelle les instructions qui modifieront la variable titre_paragraphe. On veut afficher en tête de page:
Soit: Entrez les identifiants des clients Lorsque les champs de formulaire sont vides.
champs du formulaire video
exemple de page statique
Soit: VALIDER la saisie: {} => {} Lorsque les champs name et pass ont été renseignés. Les symboles {} devront être remplacés par leur valeur à l’aide d’une expression formatée en python. (utiliser .format).
champs du formulaire renseigné
exemple de page statique
Enfin, modifier la variable table_affiche pour afficher dans le tableau TOUS les éléments de la table clients_login
A partir de la base de données du TP précédent, vous allez créer une nouvelle page utilisant des boutons radio.
Ces boutons radio permettront de choisir les noms clients à afficher, en partageant l’alphabet en 3 parties.
La page devrait ressembler à l’image ci-dessous:
Pour des projets d’applications web plus conséquents, on pourra se tourner vers des frameworks qui vont créer un environnement de travail plus complet:
schéma relationnel de la base de données films-realisateurs, base de libreoffice
TP Browser SQL: Base, SQLite Browser, Access
Base de données sur FILMS et REALISATEURS
Base de Libre Office
Démarrage
Lancer Libre Office > Base. Au demarrage:
choisir “Créer une nouvelle base de données”
nommer cette base de données. Par exemple films_cultes. L’extension placée par le logiciel est .obd
Structurer et renseigner les données
Commençons par créer les 2 tables films et realisateurs.
créer une nouvelle table
remplir les champs nom et domaine pour chaque attribut
1: selectionner la colonne de l'attribut id_films, 2: clic droit, choisir Primary Key
1: sauvegarder la table, 2: renseigner le nom: films
faire de même pour créer la table realisateurs
On va maintenant créer une association entre les 2 tables.
menu Tools: choisir Relationships
1: ajouter chacune des tables dans le canvas, 2: cliquer sur films.id_rea et le glisser sur realisateurs.id_rea
bravo! vous avez créé l'association entre les 2 tables
La clé secondaire films.id_rea est maintenant liée à la clé primaire realisateurs.id_rea.
Il reste maintenant à renseigner les données pour chacune des tables. Commencer par celle realisateurs. Car les tables sont liées par l’attribut realisateurs.id_rea
1: clic droit sur la table realisateurs, 2: open
renseigner les données
id_rea
nom
prenom
annee_naissance
1
Kitano
Takeshi
1947
2
Burton
Tim
1958
3
Tarantino
Quentin
1963
4
Tati
Jacques
1907
5
Hitchcock
Alfred
1899
6
Almodovar
Pedro
1949
7
Kitamura
Ryûhei
1969
puis ouvrir la table films
id_film
titre
date
id_rea
1
Hana-bi
1997
2
Big fish
2003
3
Edward aux mains d’argent
1990
4
Sonatine
1993
5
Pulp Fiction
1995
6
Play Time
1967
7
Vertigo
1958
8
Psychose
1960
9
Parle avec elle
2002
10
Mon oncle
1958
11
Volver
2006
12
Reservoir Dogs
1992
13
Alive
2003
14
Godzilla: Final Wars
2004
renseigner les données
Requêtes sur la base de données
Les requêtes seront réalisées en mode interactif pour démarrer.
Choisir 1. Database Queries puis 2. Design View
Ajouter les tables films et realisateurs dans le canvas
construire la requête comme sur l'image ci-contre
passer en mode SQL avec le bouton (jaune) de la barre de menu
Executer la requête SQL avec le bouton (vert)
Observer la vue présentée par le logiciel (tableau). Cette vue peut être obtenue avec une instruction plus simple en SQL.
Mettre les symboles -- devant l’instruction SQL pour la mettre en commentaire.
Ajouter l’instruction SQL: SELECT * FROM films
Executer. Vous obtenez le même résultats…
saisie directe d'une requête SQL
Tester une nouvelle requête en mode Design View
nouvelle requête
Cette fois, on ajoute une clause sur la valeur de id_rea. Mais sans afficher l’attribut (Visible non coché).
Recopier la requête SQL générée. Executer.
nouvelle requête
Pour cette nouvelle requête en mode visuel, on selectionne des attributs des 2 tables. On applique certaines clauses.
En mode SQL: Remarquer que la clause "films"."id_rea" = "realisateurs"."id_rea" s’est mise automatiquement.
Recopier cette requête SQL.
Executer.
Questions: Ecrire les requêtes SQL pour…
Afficher toute la table films
Corriger la date de parution du film Vertigo (se renseigner sur le net)
Afficher tous les attributs du-des film-s dont le réalisateur est le 1er de la table realisateurs
tous les titres des films sortis après 1970 mais avant 2002
le titre du film, la date de sortie le nom du realisateur pour id_rea egal à 2
tous les noms des auteurs de films qui ont sorti des films après 1960, mais pas Jacques Tati.
l’année de naissance du réalisateur de Reservoir Dogs ?
Le nombre de films du réalisateur “Hitckock”
Inventer une nouvelle information à partir de cette base de donnée, necessitant une jointure entre les tables.
SQLite DBrowser
une version portable du logiciel peut être téléchargée ici: sqlitebrowser.org
Vous pouvez aussi construire les 2 tables avec SQLite DBrowser:
Commencer par construire la table realisateurs, puis celle films. Bien renseigner les clés primaires (PK) pour ces 2 tables, ainsi que la clé étrangère pour films
ajouter les lignes à chaque table, ici aussi, en commençant par realisateurs
Solutions
Tester alors les instructions SQL suivantes… Recopier ensuite l’instruction et expliquer dans chaque cas ce qui est renvoyé:
Cet exercice porte sur les tableaux et sur la programmation de base en Python.
tableaupython bases
On rappelle que len est une fonction qui prend un tableau en paramètre et renvoie sa longueur. C’est-à-dire le nombre d’éléments présents dans le tableau.
Exemple : len([12, 54, 34, 57] vaut 4.
Le but de cet exercice est de programmer différentes réductions pour un site de vente de vêtements en ligne.
On rappelle que si le prix d’un article avant réduction est de x euros,
son prix vaut 0,5x si on lui applique une réduction de 50%,
son prix vaut 0,6x si on lui applique une réduction de 40%,
son prix vaut 0,7x si on lui applique une réduction de 30%,
son prix vaut 0,8x si on lui applique une réduction de 20%,
son prix vaut 0,9x si on lui applique une réduction de 10%.
Dans le système informatique du site de vente, l’ensemble des articles qu’un client veut acheter, appelé panier, est modélisé par un tableau de flottants.
Par exemple, si un client veut acheter un pantalon à 30,50 euros, un tee-shirt à 15 euros, une paire de chaussettes à 6 euros, une jupe à 20 euros, une paire de collants à 5 euros, une robe à 35 euros et un short à 10,50 euros, le système informatique aura le tableau suivant :
tab = [30.5, 15.0, 6.0, 20.0, 5.0, 35.0, 10.5]``
Question 1
A. Écrire une fonction Python total_hors_reduction ayant pour argument le tableau des prix des articles du panier d’un client et renvoyant le total des prix de ces articles.
B. Le site de vente propose la promotion suivante comme offre de bienvenue : 20% de réduction sur le premier article de la liste, 30% de réduction sur le deuxième article de la liste (s’il y a au moins deux articles) et aucune réduction sur le reste des articles (s’il y en a).
Recopier sur la copie et compléter la fonction Python offre_bienvenue prenant en paramètre le tableau tab des prix des articles du panier d’un client et renvoyant le total à payer lorsqu’on leur applique l’offre de bienvenue.
Pour toute la suite de l’exercice, on pourra utiliser la fonction total_hors_reduction même si la question 1 n’a pas été traitée.
Question 2
Lors de la période des soldes, le site de vente propose les réductions suivantes :
si le panier contient 5 articles ou plus, une réduction globale de 50%,
si le panier contient 4 articles, une réduction globale de 40%,
si le panier contient 3 articles, une réduction globale de 30%,
si le panier contient 2 articles, une réduction globale de 20%,
si le panier contient 1 article, une réduction globale de 10%.
Proposer une fonction Python prix_solde ayant pour argument le tableau tab des prix des articles du panier d’un client et renvoyant le total des prix de ces articles lorsqu’on leur applique la réduction des soldes.
Question 3
A. Écrire une fonction minimum qui prend en paramètre un tableau tab de nombres et renvoie la valeur minimum présente dans le tableau.
B. Pour ses bons clients, le site de vente propose une offre promotionnelle, à partir de 2 articles achetés, l’article le moins cher des articles commandés est offert.
Écrire une fonction Python offre_bon_client ayant pour paramètre le tableau des prix des articles du panier d’un client et renvoyant le total à payer lorsqu’on leur applique l’offre bon client.
Question 4
Afin de diminuer le stock de ses articles dans ses entrepôts, l’entreprise imagine faire l’offre suivante à ses clients : en suivant l’ordre des articles dans le panier du client, elle considère les 3 premiers articles et offre le moins cher, puis les 3 suivants et offre le moins cher et ainsi de suite jusqu’à ce qu’il reste au plus 2 articles qui n’ont alors droit à aucune réduction.
Exemple : Si le panier du client contient un pantalon à 30,50 euros, un tee-shirt à 15 euros, une paire de chaussettes à 6 euros, une jupe à 20 euros, une paire de collants à 5 euros, une robe à 35 euros et un short à 10,50 euros, ce panier est représenté par le tableau suivant :
tab = [30.5, 15.0, 6.0, 20.0, 5.0, 35.0, 10.5]
Pour le premier groupe (le pantalon à 30,50 euros, le tee-shirt à 15 euros, la paire de chaussettes à 6 euros), l’article le moins cher, la paire de chaussettes à 6 euros, est offert. Pour le second groupe (la jupe à 20 euros, la paire de collants à 5 euros, la robe à 35 euros), la paire de collants
à 5 euros est offerte.
Donc le total après promotion de déstockage est 111 euros.
On constate que le prix après promotion de déstockage dépend de l’ordre dans lequel se présentent les articles dans le panier.
A. Proposer un panier contenant les mêmes articles que ceux de l’exemple mais ayant un prix
après promotion de déstockage différent de 111 euros.
B. Proposer un panier contenant les mêmes articles mais ayant le prix après promotion de déstockage le plus bas possible.
C. Une fois ses articles choisis, quel algorithme le client peut-il utiliser pour modifier son panier afin de s’assurer qu’il obtiendra le prix après promotion de déstockage le plus bas possible ? On ne demande pas d’écrire cet algorithme.
Bac 2021 Metropole Sept: Exercice 2
Principaux thèmes abordés : structure de données (tableaux, dictionnaires) et langages et programmation (spécification).tableauxdictionnairepython bases
La carte des liaisons possibles dans la région Occitanie est donnée en annexe 1 de l’exercice 2. Dans l’annexe 2 de l’exercice 2, les liaisons possédées par le joueur 1 sont en noir, et celles du joueur 2 en blanc. Les liaisons en gris sont encore en jeu.
Codages des structures de données utilisées :
Liste des liaisons d’un joueur : Toutes les liaisons directes (sans ville intermédiaire) construites par un joueur seront enregistrées dans une variable de type “tableau de tableaux”.
Le joueur 1 possède les lignes directes “Toulouse-Muret”, “Toulouse-Montauban”,
“Gaillac-St Sulpice” et “Muret-Pamiers” (liaisons indiquées en noir dans l’annexe 2 de l’exercice 2). Ces liaisons sont mémorisées dans la variable ci-dessous.
Remarque : Seules les liaisons directes existent, par exemple [“Toulouse”,“Muret”] ou [“Muret”,“Toulouse”]. Par contre, le tableau [“Toulouse”,“Mazamet”] n’existe pas, puisque la ligne Toulouse-Mazamet passe par Castres.
Dictionnaire associé à un joueur : On code la liste des villes et des trajets possédée
par un joueur en utilisant un dictionnaire de tableaux. Chaque clef de ce
dictionnaire est une ville de départ, et chaque valeur est un tableau contenant les
villes d’arrivée possibles en fonction des liaisons possédées par le joueur.
Le dictionnaire de tableaux du joueur 1 est donné ci-dessous :
Cette question concerne le joueur n°2 (Rappel : les liaisons possédées par le joueur n°2 sont représentées par un rectangle blanc dans l’annexe 2 de l’exercice 2).
A. Donner le tableau liaisonsJoueur2, des liaisons possédées par le joueur n°2.
B. Recopier et compléter le dictionnaire suivant, associé au joueur n°2 :
À partir du tableau de tableaux contenant les liaisons d’un joueur, on souhaite
construire le dictionnaire correspondant au joueur. Une première proposition a
abouti à la fonction construireDict ci-dessous
defconstruireDict(listeLiaisons):"""
listeLiaisons est un tableau de tableaux représentant la
liste des liaisons d'un joueur comme décrit dans le problème
"""Dict={}forliaisoninlisteLiaisons:villeA=liaison[0]villeB=liaison[1]ifnotvilleAinDict.keys():Dict[villeA]=[villeB]else:destinationsA=Dict[villeA]ifnotvilleBindestinationsA:destinationsA.append(villeB)returnDict
A. Écrire sur votre copie un assert dans la fonction construireDict qui permet
de vérifier que la listeLiaisons n’est pas vide.
B. Sur votre copie, donner le résultat de cette fonction ayant comme argument la variable liaisonsJoueur1 donnée dans l’énoncé et expliquer en quoi cette
fonction ne répond que partiellement à la demande.
C. La fonction construireDict, définie ci-dessus, est donc partiellement
inexacte. Compléter la fonction construireDict pour qu’elle génère bien l’ensemble du dictionnaire de tableaux correspondant à la liste de liaisons données en argument. À l’aide des numéros de lignes, on précisera où est inséré ce code.
1282 × 862
1318 × 878
Corrigé
Question 1
Cette liste n’est pas valide à cause de la liaison ["Luchon","Muret"]. Il n’existe pas de liaison directe entre Luchon et Muret : la ligne passe par St Gaudens. Il faudrait donc deux liaisons, ["Luchon","St Gaudens"] et ["St Gaudens","Muret"].
Les deux autres liaisons, Toulouse-Auch et Quillan-Limoux, sont bien des liaisons directes.
Question 2
A. D’après l’annexe 2, le joueur 2 possède cinq liaisons (en blanc) :
Pour les références, on numérote les lignes de la fonction de 1 (def construireDict...) à 16 (return Dict). Les lignes 2 à 5 correspondent à la docstring, et la ligne 6 est Dict={}.
A. On insère l’assertion après la docstring, entre les lignes 5 et 6 :
assertlen(listeLiaisons)>0,"la liste des liaisons est vide"
On peut aussi écrire assert listeLiaisons != [].
B. Avec liaisonsJoueur1 en argument, la fonction renvoie :
La fonction ne répond que partiellement à la demande, car elle ne traite chaque liaison que dans un seul sens, de villeA vers villeB. Il manque donc les trajets retour. Par exemple, la clé "Montauban" est absente, alors que Montauban est reliée à Toulouse. De même, "Muret" devrait contenir "Toulouse" en plus de "Pamiers".
C. Il faut faire le même traitement dans l’autre sens, de villeB vers villeA. On insère le code suivant après la ligne 15, au même niveau d’indentation que le premier if de la ligne 10, donc à l’intérieur de la boucle for :
defconstruireDict(listeLiaisons):"""
listeLiaisons est un tableau de tableaux représentant la
liste des liaisons d'un joueur comme décrit dans le problème
"""assertlen(listeLiaisons)>0,"la liste des liaisons est vide"Dict={}forliaisoninlisteLiaisons:villeA=liaison[0]villeB=liaison[1]# sens villeA -> villeBifnotvilleAinDict.keys():Dict[villeA]=[villeB]else:destinationsA=Dict[villeA]ifnotvilleBindestinationsA:destinationsA.append(villeB)# sens villeB -> villeAifnotvilleBinDict.keys():Dict[villeB]=[villeA]else:destinationsB=Dict[villeB]ifnotvilleAindestinationsB:destinationsB.append(villeA)returnDict
Appliquée à liaisonsJoueur1, cette fonction renvoie bien le dictionnaire DictJoueur1 donné dans l’énoncé.
Bac 2021 Metropole Sept: Exercice 5
Principaux thèmes abordés : Traitement de données en tables (CSV) et langages et programmation (spécification).
tableaupython basescsv
Afin d’améliorer l’ergonomie d’un logiciel de traitement des inscriptions dans une université, un programmeur souhaite exploiter l’intelligence artificielle pour renseigner certains champs par auto-complétion. Il s’intéresse au descripteur « genre » (masculin, féminin ou indéterminé).
Pour cela il propose d’exploiter les dernières lettres du prénom
pour proposer automatiquement le genre.
Pour vérifier son hypothèse, il récupère un fichier CSV associant plus de 60 000 prénoms du monde entier au genre de la personne portant ce prénom. En utilisant seulement la dernière lettre, le taux de réussite de sa démarche est de 72,9% avec la fonction définie ci-dessous :
defgenre(prenom):liste_M=['f','d','c','b','o','n','m','l','k','j','é','h','w','v','u','t','s','r','q','p','i','þ','z','x','ç','ö','ã','â','ï','g']liste_F=['e','a','ä','ü','y','ë']ifprenom[len(prenom)-1].lower()inliste_M:return"M"elifprenom[len(prenom)-1].lower()inliste_F:return"F"else:return"I"# Pour rappel, C.lower() convertit le caractère C en minuscule.
1. Appropriation
A. Expliquer ce qu’est un fichier CSV.
B. Donner le type de l’argument prenom de la fonction genre, et le type de la réponse renvoyée.
2. Développement
Pour effectuer son étude sur les prénoms à partir du fichier CSV, le programmeur souhaite utiliser la bibliothèque csv.
A. La bibliothèque csv est un module natif du moteur python.
Donner, dans ce cas, l’instruction d’importation.
B. Au cours du développement de son projet, le programmeur souhaite insérer une assertion sur l’argument donné à la fonction.
Proposer une assertion sur le type de l’argument qui corrige une erreur lorsque
le type ne correspond pas à celui attendu.
C. Avant le déploiement de sa solution, le programmeur décide de rendre sa fonction plus robuste.
Pour cela il veut remplacer l’assertion proposée dans la question 2.B) par une
gestion de l’argument pour éviter toutes erreurs empêchant la poursuite du programme.
Proposer alors une ou plusieurs instructions en Python utilisant l’argument afin de s’assurer que la fonction se termine quel que soit le type de l’argument.
3. Améliorations
En prenant en compte les deux dernières lettres du prénom, il parvient à augmenter son taux de réussite à 74,4%. Pour cela, son étude du fichier CSV lui permet de créer deux listes : liste_M2 pour les terminaisons de deux lettres associées aux prénoms masculins et liste_F2 pour les prénoms féminins.
Sur votre copie, recopier et modifier la structure conditionnelle (lignes 8 à 13) de la fonction genre afin de prendre en compte les terminaisons de deux lettres des listes liste_M2 et liste_F2.
Bac 2021 Etranger1: Exercice 2
Notion abordée : structures de données (dictionnaires)
dictionnairespython basestuple
Une ville souhaite gérer son parc de vélos en location partagée. L’ensemble de la flotte de vélos est stocké dans une table de données représentée en langage Python par un dictionnaire contenant des associations de type id_velo: dict_velo où id_velo est un nombre entier compris entre 1 et 199 qui correspond à l’identifiant unique du vélo et dict_velo est un dictionnaire dont les clés sont : "type", "etat", "station".
Les valeurs associées aux clés "type", "etat", "station"de dict_velo sont de type chaînes de caractères ou nombre entier :
"type" : chaîne de caractères qui peut prendre la valeur “electrique” ou
“classique”
"état" : nombre entier qui peut prendre la valeur 1 si le vélo est disponible, 0 si le vélo est en déplacement, -1 si le vélo est en panne
"station": chaînes de caractères qui identifie la station où est garé le vélo.
Dans le cas où le vélo est en déplacement ou en panne, "station" correspond à celle où il a été dernièrement stationné.
Toutes les questions de cet exercice se réfèrent à l’extrait de la table flotte fourni cidessus. L’annexe 1 présente un rappel sur les dictionnaires en langage Python.
Question 1
1.a. Que renvoie l’instruction flotte[26] ?
1.b. Que renvoie l’instruction flotte[80]["etat"] ?
1.c. Que renvoie l’instruction flotte[99]["etat"] ?
2.a. Quelles sont les valeurs possibles de la variable choix ?
2.b. Expliquer ce que renvoie la fonction lorsque l’on choisit comme paramètre l’une des valeurs possibles de la variable choix.
Question 3
3.a. Écrire un script en langage Python qui affiche les identifiants (id_velo) de tous les vélos disponibles à la station "Citadelle".
3.b. Écrire un script en langage Python qui permet d’afficher l’identifiant
(id_velo) et la station de tous les vélos électriques qui ne sont pas en panne.
Question 4
On dispose d’une table de données des positions GPS de toutes les stations,
dont un extrait est donné ci-dessous. Cette table est stockée sous forme d’un
dictionnaire.
Chaque élément du dictionnaire est du type:
'nom de la station' : (latitude, longitude)
On admet que l’on dispose d’une fonction distance(p1, p2) permettant de
renvoyer la distance en mètres entre deux positions données par leurs
coordonnées GPS (latitude et longitude).
Cette fonction prend en paramètre deux tuples représentant les coordonnées des
deux positions GPS et renvoie un nombre entier représentant cette distance en
mètres.
Par exemple, distance((49.8905, 2.2967), (49.8912, 2.3016)) renvoie 9591
Écrire une fonction qui prend en paramètre les coordonnées GPS de l’utilisateur
sous forme d’un tuple et qui renvoie, pour chaque station située à moins de 800
mètres de l’utilisateur :
le nom de la station ;
la distance entre l’utilisateur et la station ;
les identifiants des vélos disponibles dans cette station.
Une station où aucun vélo n’est disponible ne doit pas être affichée.
Corrigé
Question 1
1.a.flotte[26] renvoie le dictionnaire associé à la clé 26 :
1.b.flotte[80] vaut {"type" : "classique", "etat" : 0, "station" : "Saint-Leu"}, donc flotte[80]["etat"] renvoie 0 (le vélo est en déplacement).
1.c. La clé 99 n’existe pas dans le dictionnaire flotte. L’instruction provoque une erreur : KeyError: 99.
Question 2
2.a. La fonction compare choix à flotte[v]["type"]. Les valeurs possibles sont donc les deux types de vélo : "electrique" ou "classique".
2.b. La fonction parcourt les vélos de la flotte dans l’ordre. Elle renvoie le nom de la station du premier vélo trouvé qui est du type demandé et disponible (etat == 1). Le return interrompt la boucle dès le premier vélo trouvé.
defstations_proches(position):"""
position : tuple (latitude, longitude) de l'utilisateur
renvoie une liste de tuples (nom_station, distance, liste_velos_disponibles)
pour les stations à moins de 800 m ayant au moins un vélo disponible
"""resultat=[]fornominstations:d=distance(position,stations[nom])ifd<800:# recherche des vélos disponibles dans cette stationvelos_dispo=[]forid_veloinflotte:ifflotte[id_velo]["station"]==nomandflotte[id_velo]["etat"]==1:velos_dispo.append(id_velo)# on ne garde la station que si au moins un vélo est disponibleiflen(velos_dispo)>0:resultat.append((nom,d,velos_dispo))returnresultat
Prefecture 303 m - vélos disponibles : [12]
Coliseum 560 m - vélos disponibles : [26]
Jacobins 513 m - vélos disponibles : [74]
La station Saint-Leu est à environ 751 m, donc à moins de 800 m, mais elle n’est pas affichée : aucun vélo n’y est disponible (le vélo 80 est en déplacement et le vélo 83 est en panne).
Le principe est le suivant. Pour chaque station, on calcule sa distance à l’utilisateur. Si cette distance est inférieure à 800 m, on construit la liste des identifiants des vélos disponibles (etat == 1) garés dans cette station. On n’ajoute la station au résultat que si cette liste n’est pas vide.
donnees structurees 1
Bac 2024 Asie J2: Exercice 2
Cet exercice porte sur la programmation orientée objet et les structures de données linéaires.POOpile
Cet exercice est composé de 2 parties indépendantes.
Dans cet exercice, on appelle parenthèses les couples de caractères (), {} et [].
Pour chaque couple de parenthèses, la première parenthèse est appelée la parenthèse ouvrante du couple et la seconde est appelée la parenthèse fermante du couple.
On dit qu’une expression (chaine de caractères) est bien parenthésée si:
chaque parenthèse ouvrante correspond à une parenthèse fermante de même type ;
les expressions comprises entre parenthèses sont des expressions bien parenthésées.
Par exemple, l’expression tab[2*(i + 4)] - tab[3] est bien parenthésée.
En revanche, l’expression tab[2*(i + 4] - tab[3) n’est pas bien parenthésée, car la première parenthèse fermante ] devrait correspondre à la dernière parenthèse
ouvrante (.
Déterminer si l’expression [2*(i+1)-3) for i in range(3, 10)] est bien parenthésée. Justifier votre réponse.
Partie A
On peut observer que, si les parenthèses vont par couple, une expression bien parenthésée contient autant de parenthèses ouvrantes que de parenthèses fermantes.
On se propose d’écrire une fonction qui vérifie si une chaine de caractères est bien parenthésée.
Écrire une fonction compte_ouvrante qui prend en paramètre une chaine de caractères txt et qui renvoie le nombre de parenthèses ouvrantes qu’il contient.
Écrire une fonction compte_fermante qui prend en paramètre une chaine de caractères txt et qui renvoie le nombre de parenthèses fermantes qu’il contient.
En utilisant les deux fonctions précédentes, écrire une fonction bon_compte qui
prend en paramètre une chaine de caractères txt et qui renvoie True si txt a autant de parenthèses ouvrantes que parenthèses fermantes et False sinon.
Donner un exemple de chaine de caractères pour laquelle bon_compte renvoie True alors qu’elle n’est pas bien parenthésée.
Partie B
Comme l’algorithme précédent n’est pas suffisant, on se propose d’implémenter un algorithme utilisant une structure linéaire de pile.
On se propose d’écrire une classe Pile qui implémente la structure de pile.
classPile:def__init__(self):self.contenu=[]defest_vide(self):returnlen(self.contenu)==0defempiler(self,elt):...defdepiler(self):ifself.est_vide():return"La pile est vide."return...
Compléter les lignes 9 et 14 du code précédent pour que la méthode empiler permette d’empiler un élément elt dans une pile et que la méthode depiler permette de dépiler une pile en renvoyant l’élément dépilé. Vous n’écrirez que le code des deux méthodes.
Un algorithme permettant de vérifier si une expression est bien parenthésée consiste à:
créer une pile vide p ;
parcourir l’expression en testant chaque caractère :
– si c’est une parenthèse ouvrante, on l’empile dans p ;
– si c’est une parenthèse fermante, on dépile p ;
si les deux caractères correspondent à un couple de
parenthèses, on continue le parcours,
sinon l’expression n’est pas bien parenthésée ;
– sinon on continue le parcours.
Si l’expression a été entièrement parcourue, on teste la pile ; l’expression est bien parenthésée si la pile est vide.
Déterminer le nombre de comparaisons effectuées si on applique l’algorithme précédent à la chaine de caractères tab[2*(i + 4)] - tab[3]. En déduire le nombre maximum de comparaisons effectuées si on applique l’algorithme
précédent à une chaine de caractères de taille n (attention aux comparaisons de la classe pile).
Écrire une fonction est_bien_parenthesee qui prend en paramètre une chaine de caractères et qui implémente l’algorithme précédent.
Bac 2022 Polynesie: Exercice 4
Cet exercice traite du thème « structures de données », et principalement des piles.POOpile
La classe Pile utilisée dans cet exercice est implémentée en utilisant des listes Python et propose quatre éléments d’interface :
Un constructeur qui permet de créer une pile vide, représentée par [] ;
La méthode est_vide() qui renvoie True si l’objet est une pile ne contenant aucun élément, et Falsesinon ;
La méthode empiler qui prend un objet quelconque en paramètre et ajoute cet
objet au sommet de la pile. Dans la représentation de la pile dans la console, cet objet apparaît à droite des autres éléments de la pile ;
La méthode depiler qui renvoie l’objet présent au sommet de la pile et le retire de la pile.
Recopier sur la copie les lignes 6 et 8 en complétant les points de suspension.
On créé dans la console la pile A représentée par [1, 2, 3, 4]
Question 2
A. Donner la valeur renvoyée par l’appel A.est_triee().
B. Donner le contenu de la pile A après l’exécution de cette instruction.
On souhaite maintenant écrire le code d’une méthode depileMaxd’une pile non vide ne contenant que des nombres entiers et renvoyant le plus grand élément de cette pile en le retirant de la pile.
Après l’exécution de p.depileMax(), le nombre d’éléments de la pile p diminue donc de 1.
B. Donner les contenus successifs des piles B et q
avant la ligne 3,
avant la ligne 5,
à la fin de l’exécution de la fonction traiter lorsque la fonction traiter est appliquée sur la pile B contenant [1, 6, 4, 3, 7, 2].
C. Expliquer le traitement effectué par cette méthode.
Bac 2022 Metropole 1: Exercice 1
Cet exercice composé de deux parties A et B, porte sur les structures de données.pile
Partie A : Expression correctement parenthésée
On veut déterminer si une expression arithmétique est correctement parenthésée.
Pour chaque parenthèse fermante “)” correspond une parenthèse précédemment
ouverte “(”.
L’expression arithmétique “(2 + 3) × (18/(4 + 2” est non correctement
parenthésée.
Pour simplifier les expressions arithmétiques, on enregistre, dans une structure de données, uniquement les parenthèses dans leur ordre d’apparition.
On appelle expression simplifiée cette structure.
1158 × 248
Question 1
Indiquer si la phrase « les éléments sont maintenant retirés (pour être lus) de cette structure de données dans le même ordre qu’ils y ont été ajoutés lors de l’enregistrement » décrit le comportement d’une file ou d’une pile. Justifier.
Pour vérifier le parenthésage, on peut utiliser une variable controleur qui :
est un nombre entier égal à 0 en début d’analyse de l’expression simplifiée ;
augmente de 1 si l’on rencontre une parenthèse ouvrante “(” ;
diminue de 1 si l’on rencontre une parenthèse fermante “)”.
Exemple : On considère l’ expression simplifiée A : “( )( ( ) )”
Lors de l’analyse de l’expression A, controleur (initialement égal à 0) prend
successivement pour valeur 1, 0, 1, 2, 1, 0. Le parenthésage est correct.
Question 2
Écrire, pour chacune des 2 expressions simplifiées B et C suivantes, les valeurs successives prises par la variable controleur lors de leur analyse.
Expression simplifiée B : " ((( )( )"
Expression simplifiée C : “(( )))(”
Question 3
L’expression simplifiée B précédente est mal parenthésée (parenthèses fermantes
manquantes) car le controleur est différent de zéro en fin d’analyse.
L’expression simplifiée C précédente est également mal parenthésée (parenthèse
fermante sans parenthèse ouvrante) car le controleur prend une valeur
négative pendant l’analyse.
Recopier et compléter uniquement les lignes 13 et 16 du code ci-dessous pour
que la fonction parenthesage_correct réponde à sa description.
defparenthesage_correct(expression):"""fonction retournant True si l'expression arithmétique
simplifiée (str) est correctement parenthésée, False
sinon.
Condition: expression ne contient que des parenthèses
ouvrantes et fermantes """controleur=0forparentheseinexpression:#pour chaque parenthèseifparenthese=='(':controleur=controleur+1else:# parenthese == ')'controleur=controleur-1ifcontroleur...:# test 1 (à recopier et compléter)#parenthèse fermante sans parenthèse ouvrantereturnFalseifcontroleur...:# test 2 (à recopier et compléter)returnTrue#le parenthésage est correctelse:returnFalse#parenthèse(s) fermante(s) manquante(s)
Partie B : Texte correctement balisé
On peut faire l’analogie entre le texte simplifié des fichiers HTML (uniquement
constitué de balises ouvrantes et fermantes ) et les expressions
parenthésées :
Par exemple, l’expression HTML simplifiée :
"<p><strong><em></em></strong></p>" est correctement balisée.
On ne tiendra pas compte dans cette partie des balises ne comportant pas de
fermeture comme <br> ou <img …>.
Afin de vérifier qu’une expression HTML simplifiée est correctement balisé, on peut utiliser une pile (initialement vide) selon l’algorithme suivant :
On parcourt successivement chaque balise de l’expression :
lorsque l’on rencontre une balise ouvrante, on l’empile ;
lorsque l’on rencontre une balise fermante :
si la pile est vide, alors l’analyse s’arrête : le balisage est incorrect ,
sinon, on dépile et on vérifie que les deux balises (la balise fermante
rencontrée et la balise ouvrante dépilée) correspondent (c’est-à-dire ont le
même nom) si ce n’est pas le cas, l’analyse s’arrête (balisage incorrect).
Exemple : État de la pile lors du déroulement de cet algorithme pour l’expression simplifiée "<p><em></p></em>" qui n’est pas correctement balisée.
État de la pile lors du déroulement de l’algorithme - 1242 × 258
Question 4
Cette question traite de l’état de la pile lors du déroulement de l’algorithme.
A. Représenter la pile à chaque étape du déroulement de cet algorithme pour
l’expression "<p><em></em></p>" (balisage correct).
B. Indiquer quelle condition simple (sur le contenu de la pile) permet alors de dire que le balisage est correct lorsque toute l’expression HTML simplifiée a été entièrement parcourue, sans que l’analyse ne s’arrête.
Question 5
Une expression HTML correctement balisée contient 12 balises.
Indiquer le nombre d’éléments que pourrait contenir au maximum la pile lors de
son analyse.
Bac 2022 Metropole 2: Exercice 2
Cet exercice porte sur les structures de données.pilerecursivité
La poussette est un jeu de cartes en solitaire. Cet exercice propose une version simplifiée de ce jeu basée sur des nombres.
On considère une pile constituée de nombres entiers tirés aléatoirement. Le jeu
consiste à réduire la pile suivant la règle suivante : quand la pile contient du haut vers le bas un triplet dont les termes du haut et du bas sont de même parité, on supprime l’élément central.
Par exemple :
Si la pile contient du haut vers le bas, le triplet 1 0 3, on supprime le 0.
Si la pile contient du haut vers le bas, le triplet 1 0 8, la pile reste inchangée.
On parcourt la pile ainsi de haut en bas et on procède aux réductions. Arrivé en bas de la pile, on recommence la réduction en repartant du sommet de la pile jusqu’à ce que la pile ne soit plus réductible. Une partie est « gagnante » lorsque la pile finale est réduite à deux éléments exactement.
Voici un exemple détaillé de déroulement d’une partie.
1128 × 412
Question 1
A. Donner les différentes étapes de réduction de la pile suivante :
524 × 394
B. Parmi les piles proposées ci-dessous, donner celle qui est gagnante.
952 × 468
L’interface d’une pile est proposée ci-dessous. On utilisera uniquement les fonctions figurant dans le tableau suivant :
Structure de données abstraite : Pile
creer_pile_vide()
renvoie une pile vide
est_vide(p)
renvoie True si p est vide, False sinon
empiler(p, element)
ajoute element au sommet de p
depiler(p)
retire l’élément au sommet de p et le renvoie
sommet(p)
renvoie l’élément au sommet de p sans le retirer de p
taille(p)
renvoie le nombre d’éléments de p
Question 2
La fonction reduire_triplet_au_sommet permet de supprimer l’élément
central des trois premiers éléments en partant du haut de la pile, si l’élément du bas et du haut sont de même parité. Les éléments dépilés et non supprimés sont replacés dans le bon ordre dans la pile.
Recopier et compléter sur la copie le code de la fonction
reduire_triplet_au_sommet prenant une pile p en paramètre et qui la
modifie en place. Cette fonction ne renvoie donc rien.
On se propose maintenant d’écrire une fonction parcourir_pile_en_reduisant qui parcourt la pile du haut vers le bas en procédant aux réductions pour chaque triplet rencontré quand cela est possible.
A. Donner la taille minimale que doit avoir une pile pour être réductible.
Partant d’une pile d’entiers p, on propose ici d’implémenter une fonction récursive jouer renvoyant la pile p entièrement simplifiée. Une fois la pile parcourue de haut en bas et réduite, on procède à nouveau à sa réduction à condition que cela soit possible. Ainsi :
Si la pile p n’a pas subi de réduction, on la renvoie.
Sinon on appelle à nouveau la fonction jouer , prenant en paramètre la
pile réduite.
Recopier et compléter sur la copie le code ci-dessous :
Cet exercice traite du thème « algorithmique », et principalement des algorithmes sur les arbres binaires.
arbre binairehauteur
On manipule ici les arbres binaires avec trois fonctions :
est_vide(A) qui renvoie True si l’arbre binaire A est vide, False s’il ne l’est pas ;
sous_arbre_gauche(A) qui renvoie le sous-arbre gauche de l’arbre binaire A ;
sous_arbre_droit(A) qui renvoie le sous-arbre droit de l’arbre binaire A.
L’arbre binaire renvoyé par les fonctions sous_arbre_gauche et sous_arbre_droit peut éventuellement être l’arbre vide.
On définit la hauteur d’un arbre binaire non vide de la façon suivante :
si ses sous-arbres gauche et droit sont vides, sa hauteur est 0 ;
si l’un des deux au moins est non vide, alors sa hauteur est égale à 1 + M, où M est la plus grande des hauteurs de ses sous-arbres (gauche et droit) non vides.
Question 1
A. Donner la hauteur de l’arbre ci-dessous.
304 × 232
B. Dessiner sur la copie un arbre binaire de hauteur 4.
La hauteur d’un arbre est calculée par l’algorithme récursif suivant :
Algorithme hauteur(A):
test d'assertion : A est supposé non vide
si sous_arbre_gauche(A) vide et sous_arbre_droit(A) vide:
renvoyer 0
sinon, si sous_arbre_gauche(A) vide:
renvoyer 1 + hauteur(sous_arbre_droit(A))
sinon, si ... :
renvoyer ...
sinon:
renvoyer 1 + max(hauteur(sous_arbre_gauche(A)),
hauteur(sous_arbre_droit(A)))
Question 2
Recopier sur la copie les lignes 7 et 8 en complétant les points de suspension.
Question 3
On considère un arbre binaire R dont on note G le sous-arbre gauche et D le sous-arbre droit. On suppose que R est de hauteur 4 et G de hauteur 2.
A. Justifier le fait que D n’est pas l’arbre vide et déterminer sa hauteur.
B. Illustrer cette situation par un dessin.
Soit un arbre binaire non vide de hauteur h. On note n le nombre de nœuds de cet arbre. On admet que $h+1 \leqslant n \leqslant 2^{h+1}−1$.
Question 4
A. Vérifier ces inégalités sur l’arbre binaire de la question 1.A.
B. Expliquer comment construire un arbre binaire de hauteur h quelconque
ayant h+1 nœuds.
C. Expliquer comment construire un arbre binaire de hauteur h quelconque ayant
$2^{h+1}−1$ nœuds.
Indication : $2^{h+1}−1 = 1+2+4+...+2^h$
L’objectif de la fin de l’exercice est d’écrire le code d’une fonction fabrique(h, n) qui prend comme paramètres deux nombres entiers positifs h et n tels que $h+1 \leqslant n \leqslant 2^{h+1}−1$, et qui renvoie un arbre binaire de hauteur h à n nœuds.
Pour cela, on a besoin des deux fonctions suivantes:
arbre_vide(), qui renvoie un arbre vide ;
arbre(gauche, droit) qui renvoie l’arbre de fils gauche gauche et de fils
droit droit.
Question 5
Recopier sur la copie l’arbre binaire ci-dessous et numéroter ses nœuds de 1 en
1 en commençant à 1, en effectuant un parcours en profondeur préfixe.
546 × 322
La fonction fabrique ci-dessous a pour but de répondre au problème posé. Pour cela, la fonction annexe utilise la valeur de n, qu’elle peut modifier, et renvoie un arbre binaire de hauteur hauteur_max dont le nombre de nœuds est égal à la valeur de n au moment de son appel.
Recopier sur la copie les lignes 7 et 11 en complétant les points de suspension.
Bac 2022 Metropole 1: Exercice 4
Cet exercice, composé de deux parties A et B, porte sur le parcours des arbres
binaires, le principe “diviser pour régner” et la récursivité.
arbreparcoursFilerécursivité
Cet exercice traite du calcul de la somme d’un arbre binaire. Cette somme consiste à additionner toutes les valeurs numériques contenues dans les nœuds de l’arbre.
L’arbre utilisé dans les parties A et B est le suivant :
314 × 252
Partie A : Parcours d’un arbre
Question 1
Donner la somme de l’arbre précédent. Justifier la réponse en explicitant le calcul qui a permis de l’obtenir.
Question 2
Indiquer la lettre correspondante aux noms ‘racine’, ‘feuille’, ‘nœud’, ‘SAG’ (Sous Arbre Gauche) et ‘SAD’ (Sous Arbre Droit). Chaque lettre A, B, C, D et E devra être utilisée une seule fois.
Arbre avec les lettres à associer - 578 × 310
Question 3
Parmi les quatre propositions A, B, C et D ci-dessous, donnant un parcours en
largeur d’abord de l’arbre, une seule est correcte. Indiquer laquelle.
Proposition A : 7 - 6 - 4 - 3 - 9 - 2 - 1
Proposition B : 3 - 6 - 7 - 4 - 2 - 9 - 1
Proposition C : 3 - 6 - 2 - 7 - 4 - 9 - 1
Proposition D : 7 - 4 - 6 - 9 - 1 - 2 – 3
Question 4
Écrire en langage Python la fonction somme qui prend en paramètre une liste de
nombres et qui renvoie la somme de ses éléments.
Exemple : somme([1, 2, 3, 4]) est égale à 10.
Question 5
La fonction parcourir(arbre) pourrait se traduire en langage naturel par :
Donner le type de parcours obtenu grâce à la fonction parcourir.
Partie B : Méthode ‘diviser pour régner’
diviser pour regner
Question 6
Parmi les quatre propositions A,B, C et D ci-dessous, indiquer la seule
proposition correcte.
En informatique, le principe diviser pour régner signifie :
Proposition A: diviser une fonction en deux fonctions plus petites
Proposition B: utiliser plusieurs modules
Proposition C: séparer les informations en fonction de leur types
Proposition D: diviser un problème en deux problèmes plus petits et
indépendants.
Question 7
L’arbre présenté dans le problème peut être décomposé en racine et sous
arbres :
376 × 258
Indiquer dans l’esprit de ‘diviser pour régner’ l’égalité donnant la somme d’un arbre en fonction de la somme des sous arbres et de la valeur numérique de la racine.
Question 8
Écrire en langage Python une fonction récursive calcul_somme(arbre).
Cette fonction calcule la somme de l’arbre passé en paramètre.
Les fonctions suivantes sont disponibles :
est_vide(arbre) : renvoie True si arbreest vide et renvoie False
sinon ;
valeur_racine(arbre) : renvoie la valeur numérique de la racine de
arbre;
arbre_gauche(arbre) : renvoie le sous arbre gauche de arbre;
arbre_droit(arbre) : renvoie le sous arbre droit de arbre.
Bac 2022 Metropole 2: Exercice 1
Cet exercice porte sur les arbres binaires de recherche, la programmation orientée objet et la récursivité.
ABRPOOrécursivité
Dans cet exercice, la taille d’un arbre est le nombre de nœuds qu’il contient. Sa hauteur est le nombre de nœuds du plus long chemin qui joint le nœud racine à l’une des feuilles (nœuds sans sous-arbres). On convient que la hauteur d’un arbre ne contenant qu’un nœud vaut 1 et la hauteur de l’arbre vide vaut 0.
Question 1
On considère l’arbre binaire représenté ci-dessous:
Figure 1 - 390 × 370
A. Donner la taille de cet arbre.
B. Donner la hauteur de cet arbre.
C. Représenter sur la copie le sous-arbre droit du nœud de valeur 15.
D. Justifier que l’arbre de la figure 1 est un arbre binaire de recherche.
E. On insère la valeur 17 dans l’arbre de la figure 1 de telle sorte que 17 soit une nouvelle feuille de l’arbre et que le nouvel arbre obtenu soit encore un arbre binaire de recherche. Représenter sur la copie ce nouvel arbre.
Question 2
On considère la classe Noeud définie de la façon suivante en Python :
A. Parmi les trois instructions (A), (B) et (C) suivantes, écrire
sur la copie la lettre correspondant à celle qui construit et
stocke dans la variable abr l’arbre représenté ci-contre.
B. Recopier et compléter la ligne 7 du code de la fonction ins ci-dessous qui prend en paramètres une valeur v et un arbre binaire de recherche abr et qui renvoie l’arbre obtenu suite à l’insertion de la valeur v dans l’arbre abr. Les lignes 8 et 9 permettent de ne pas insérer la valeur v si celle-ci est déjà présente dans abr.
La fonction nb_sup prend en paramètres une valeur v et un arbre binaire de
recherche abr et renvoie le nombre de valeurs supérieures ou égales à la valeur v dans l’arbre abr.
Le code de cette fonction nb_sup est donné ci-dessous :
A. On exécute l’instruction nb_sup(16, abr) dans laquelle abr est l’arbre
initial de la figure 1. Déterminer le nombre d’appels à la fonction nb_sup.
B. L’arbre passé en paramètre étant un arbre binaire de recherche, on peut
améliorer la fonction nb_sup précédente afin de réduire ce nombre d’appels.
Écrire sur la copie le code modifié de cette fonction.
Bac 2023 Centres etrangers J4
(extrait du sujet)tri fusion
Le grossiste enregistre dans la liste sommes les montants des commandes,
avant réduction, que des clients ont passées dans son magasin.
Par exemple : sommes = [140, 78, 115, 94, 46, 108, 55, 53]
Il va utiliser la méthode de tri-fusion pour trier la liste sommes dans l’ordre
croissant.
L’algorithme du tri-fusion est naturellement décrit de façon récursive (dans toute
la suite, on supposera pour simplifier que le nombre d’éléments de la liste est
une puissance de 2) :
si la liste n’a qu’un ou aucun élément, elle est déjà triée,
sinon:
on sépare la liste initiale en deux listes de même taille,
on applique récursivement l’algorithme sur ces deux listes,
on fusionne les deux listes triées obtenues en une seule liste triée.
On trouve ci-dessous un exemple de déroulement de cet algorithme pour la liste
[140,78,115,94] de 4 éléments :
division et tri fusion
{.class width=1072 height=478px}
a. Appliquer sur votre copie, de la même façon que dans l’exemple précédent,
le déroulement de l’algorithme pour la liste suivante :
[46, 108, 55, 53]
On rappelle que l’appel L.append(x) ajoute l’élément x à la fin de la liste L et que
len(L) renvoie la taille de la liste L.
b. La fonction fusion ci-dessous renvoie une liste de valeurs triées à partir des
deux listes liste1 et liste2 préalablement triées. Ecrire sur la copie l’instruction à
placer à la ligne 4 du code de la fonction fusion :
c. Recopier et compléter sur la copie la fonction récursive tri_fusion suivante, qui prend en paramètre une liste non triée et la renvoie sous la
forme d’une nouvelle liste triée.
On utilisera la fonction fusion de la question précédente.
Exemple : tri_fusion([140,115,78,94]) doit renvoyer
[78,94,115,140]
Aide Python : si L est une liste, l’instruction L[i:j] renvoie la liste
constituée des éléments de L indexés de i à j-1.
Par exemple, si L=[5,4,8,7,3], L[2:4] vaut [8,7].
deftri_fusion(liste):iflen(liste)<=1:returnliste# a completer
Bac 2021 Polynesie Exercice 1
Algorithmes de triinsertiontri fusioncomplexité
Cet exercice traite principalement du thème « algorithmique, langages et
programmation ». Le but est de comparer le tri par insertion (l’un des algorithmes étudiés en 1ère NSI pour trier un tableau) avec le tri fusion (un algorithme qui applique le principe de « diviser pour régner »).
Partie A : Manipulation d’une liste en Python
Donner les affichages obtenus après l’exécution du code Python suivant.
Écrire un code Python permettant d’afficher les éléments d’indice 2 à 4 de la liste notes
Partie B : Tri par insertion
Le tri par insertion est un algorithme efficace qui s’inspire de la façon dont on peut trier une poignée de cartes. On commence avec une seule carte dans la main gauche (les autres cartes sont en tas sur la table) puis on pioche la carte suivante et on l’insère au bon endroit dans la main gauche.
Voici une implémentation en Python de cet algorithme. Recopier et compléter les
lignes 6 et 7 surlignées (uniquement celles-ci).
deftri_insertion(liste):""" trie par insertion la liste en paramètre """forindice_courantinrange(1,len(liste)):element_a_inserer=liste[indice_courant]i=indice_courant-1whilei>=0andliste[i]>.................:liste[...........]=liste[...........]i=i-1liste[i+1]=element_a_inserer
On a écrit dans la console les instructions suivantes :
On a obtenu l’affichage suivant : [3, 7, 8, 9, 12, 14, 17, 18]
On s’interroge sur les étapes lors de l’exécution de tri_insertion(notes)
Donner le contenu de la liste notes après le premier passage dans la boucle for.
Donner le contenu de la liste notes après le troisième passage dans la boucle
for.
Quelle est la complexité algorithmique de cet algorithme dans le meilleur des cas? (celui où la liste en paramètre est déjà triée). Justifiez.
Partie C : Tri fusion
L’algorithme de tri fusion suit le principe de « diviser pour régner ».
Si le tableau à trier n’a qu’un élément, il est déjà trié.
Sinon, séparer le tableau en deux parties à peu près égales.
Trier les deux parties avec l’algorithme de tri fusion.
Fusionner les deux tableaux triés en un seul tableau.
source wikipedia
Cet algorithme est-il itératif ou récursif ? Justifier en une phrase.
Expliquer en quelques lignes comment faire pour rassembler dans une main deux tas déjà triés de cartes, la carte en haut d’un tas étant la plus petite de ce même tas ; la deuxième carte d’un tas n’étant visible qu’après avoir retiré la première carte de ce tas.
À la fin du procédé, les cartes en main doivent être triées par ordre croissant.
Une fonction fusionner a été implémentée en Python en s’inspirant du procédé de la
question précédente. Elle prend quatre arguments : la liste qui est en train d’être triée, l’indice où commence la sous-liste de gauche à fusionner, l’indice où termine cette sous-liste, et l’indice où se termine la sous-liste de droite.
Voici une implémentation de l’algorithme de tri fusion. Recopier et compléter les lignes 8, 9 et 10 surlignées (uniquement celles-ci).
frommathimportfloordeftri_fusion(liste,i_debut,i_fin):""" trie par fusion la liste en paramètre depuis
i_debut jusqu’à i_fin """ifi_debut<i_fin:i_partage=floor((i_debut+i_fin)/2)tri_fusion(liste,i_debut,..............................)tri_fusion(liste,..............................,i_fin)fusionner(liste,...............,.............,.............)
Remarque : la fonction floor renvoie la partie entière du nombre passé en paramètre.
Expliquer le rôle de la première ligne du code de la question précédente.
Partie D : Comparaison du tri par insertion et du tri fusion
Voici une illustration des étapes d’un tri effectué sur la liste [3, 41, 52, 26, 38, 57, 9, 49]
Figure 1 - 500 × 400
Quel algorithme a été utilisé : le tri par insertion ou le tri fusion ? Justifier.
Identifier le tri qui a une complexité, dans le pire des cas, en $O(n^2)$ et identifier le tri qui a une complexité, dans le pire des cas, en $O(n log_2 n)$.
Remarque : n représente la longueur de la liste à trier.
Justifier brièvement ces deux complexités.
Files
Bac 2023 Centres Etrangers: Exercice 3
Cet exercice porte sur les structures de Files
Files
Simon est un jeu de société électronique de forme circulaire comportant quatre grosses touches de couleurs différentes : rouge, vert, bleu et jaune.
Le jeu joue une séquence de couleurs que le joueur doit
mémoriser et répéter ensuite. S’il réussit, une couleur parmi les 4
est ajoutée à la fin de la séquence. La nouvelle séquence est
jouée depuis le début et le jeu continue. Dès que le joueur se
trompe, la séquence est vidée et réinitialisée avec une couleur et
une nouvelle partie commence.
Exemple de séquence jouée : rouge => bleu => rouge => jaune => bleu
Dans cet exercice nous essaierons de reproduire ce jeu.
Les quatre couleurs sont stockées dans un tuple nommé couleurs :
couleurs=("bleu","rouge","jaune","vert")
Pour stocker la séquence à afficher nous utiliserons une structure de file que l’on nommera sequence tout au long de l’exercice.
La file est une structure linéaire de type FIFO (First In First Out). Nous utiliserons durant cet exercice les fonctions suivantes :
Fonction
Description
creer_file_vide()
renvoie une file vide
est_vide(f)
renvoie True si f est vide False sinon
enfiler(f, element)
ajoute element en queue de f
defiler(f)
retire l’element en tête de f et le renvoie
taille(f)
renvoie le nombre d’elements de f
En fin de chaque séquence, le Simon tire au hasard une couleur parmi les 4 proposées.
On utilisera la fonction randint(a,b) de la bibliothèque random qui permet
d’obtenir un nombre entier compris entre a inclus et b inclus pour le tirage aléatoire.
Exemple : randint(1,5) peut renvoyer 1, 2, 3, 4 ou 5.
Recopier et compléter, sur votre copie, les … des lignes 3 et 4 de la fonction
ajout(f) qui permet de tirer au hasard une couleur et de l’ajouter à une séquence.
La fonction ajout prend en paramètre la séquence f ; elle renvoie la séquence f
modifiée (qui intègre la couleur ajoutée au format chaîne de caractères).
En cas d’erreur du joueur durant sa réponse, la partie reprend au début ; il faut donc
vider la file sequence pour recommencer à zéro en appelant vider(sequence) qui
permet de rendre la file sequence vide sans la renvoyer.
Ecrire la fonction vider qui prend en paramètre une séquence f et la vide sans la
renvoyer.
Le Simon doit afficher successivement les différentes couleurs de la séquence.
Ce rôle est confié à la fonction affich_seq(sequence), qui prend en paramètre la
file de couleurs sequence, définie par l’algorithme suivant :
on ajoute une nouvelle couleur à sequence ;
on affiche les couleurs de la séquence, une par une, avec une pause de 0,5 s entre
chaque affichage
Une fonction affichage(couleur) (dont la rédaction n’est pas demandée dans
cet exercice) permettra l’affichage de la couleur souhaitée avec couleur de type
chaîne de caractères correspondant à une des 4 couleurs.
La temporisation de 0,5 s sera effectuée avec la commande time.sleep(0.5).
Après l’exécution de la fonction affich_seq, la file sequence ne devra pas être
vidée de ses éléments.
Recopier et compléter, sur la copie, les … des lignes 4 à 10 de la fonction
affich_seq(sequence) ci-dessous :
Nous allons ici créer une fonction tour_de_jeu(sequence) qui gère le déroulement
d’un tour quelconque de jeu côté joueur. La fonction tour_de_jeu prend en
paramètre la file de couleurs sequence, qui contient un certain nombre de couleurs.
Le jeu électronique Simon commence par ajouter une couleur à la séquence et
affiche l’intégralité de la séquence.
Le joueur doit reproduire la séquence dans le même ordre. Il choisit une couleur
via la fonction saisie_joueur().
On vérifie si cette couleur est conforme à celle de la séquence.
S’il s’agit de la bonne couleur, on poursuit sinon on vide sequence.
Si le joueur arrive au bout de la séquence, il valide le tour de jeu et le jeu se
poursuit avec un nouveau tour de jeu, sinon le joueur a perdu et le jeu s’arrête.
La fonction tour_de_jeu s’arrête donc si le joueur a trouvé toutes les bonnes
couleurs de sequence dans l’ordre, ou bien dès que le joueur se trompe.
Après l’exécution de la fonction tour_de_jeu, la file sequence ne devra pas être
vidée de ses éléments en cas de victoire.
a. Afin d’obtenir la fonction tour_de_jeu(sequence) correspondant au comportement décrit ci-dessus, recopier le script ci-dessous et :
Complétez le …
Choisir parmi les propositions de syntaxes suivantes lesquelles
correspondent aux ZONES A, B, C, D, E et F figurant dans le script et les y
remplacer (il ne faut donc en choisir que six parmi les onze) :
vider(sequence)
defiler(sequence)
enfiler(sequence,c_joueur)
enfiler(stock,c_seq)
enfiler(sequence, defiler(stock))
enfiler(stock, defiler(sequence))
affich_seq(sequence)
while not est_vide(sequence):
while not est_vide(stock):
if not est_vide(sequence):
if not est_vide(stock):
b. Proposer une modification pour que la fonction se répète si le joueur trouve
toutes les couleurs de la séquence (dans ce cas, une nouvelle couleur est ajoutée) ou s’il se trompe (dans ce cas, la séquence est vidée et se voit ajouter une
nouvelle couleur). On pourra ajouter des instructions qui ne sont pas proposées
dans la question a
algorithmique
Bac 2022 Polynesie: Exercice 1
Cet exercice traite du thème «programmation», et principalement de la récursivité.récursivitéchaine strchoice
On rappelle qu’une chaîne de caractères peut être représentée en Python par un texte entre guillemets "" et que :
la fonction len renvoie la longueur de la chaîne de caractères passée en
paramètre ;
si une variable ch désigne une chaîne de caractères, alors ch[0] renvoie son premier caractère, ch[1] le deuxième, etc. ;
l’opérateur + permet de concaténer deux chaînes de caractères.
La fonction A() ci-dessous renvoie une chaîne de caractères construite suivant la règle A, en choisissant aléatoirement entre les deux cas de figure de cette règle.
B. La fonction choice([True, False]) peut renvoyer False un très grand
nombre de fois consécutives. Expliquer pourquoi ce cas de figure amènerait à
une erreur d’exécution.
Dans la suite, on considère une deuxième version de la fonction A. À présent, la fonction prend en paramètre un entier n tel que, si la valeur de n est négative ou nulle, la fonction renvoie "a". Si la valeur de n est strictement positive, elle renvoie une chaîne de caractères construite suivant la règle A avec un n décrémenté de 1, en choisissant aléatoirement entre les deux cas de figure de cette règle.
A. Recopier sur la copie et compléter aux emplacements des points de
suspension ... le code de cette nouvelle fonction A.
B. Justifier le fait qu’un appel de la forme A(n) avec n un nombre entier positif inférieur à 50, termine toujours.
On donne ci-après le code de la fonction récursive B qui prend en paramètre un entier n et qui renvoie une chaîne de caractères construite suivant la règle B.
l’appel A(1) renvoie la chaîne "a" ou la chaîne "aaa";
l’appel A(2) renvoie la chaîne "a", la chaîne "aaa" ou la chaîne "aaaaa".
Question 3
Donner toutes les chaînes possibles renvoyées par les appels B(0), B(1)
et B(2).
On suppose maintenant qu’on dispose d’une fonction raccourcir qui prend comme
paramètre une chaîne de caractères de longueur supérieure ou égale à 2, et renvoie la chaîne de caractères obtenue à partir de la chaîne initiale en lui ôtant le premier et le dernier caractère.
A. Recopier sur la copie et compléter les points de suspension ... du code de la fonction regleA ci-dessous pour qu’elle renvoie True si la chaîne passée en paramètre est construite suivant la règle A, et False sinon.
B. Écrire le code d’une fonction regleB, prenant en paramètre une chaîne de
caractères et renvoyant True si la chaîne est construite suivant la règle B,
et False sinon.
Exercice 2 24-NSIJ2ME1
Cet exercice porte sur la programmation orientée objets, les tris, les algorithmes
gloutons, la récursivité et les assertions.
récursivitéPOOgloutonprog dynamique
Cet exercice est composé de trois parties dont les deux dernières sont indépendantes
entre elles.
Dans cet exercice, l’entête des fonctions est décrit avec le type des objets en
paramètre et le type de l’objet renvoyé. Ainsi la fonction puissance qui prend un
paramètre flottant x et un entier n puis qui renvoie le flottant x**n a pour entête puissance(x: float, n: int) -> float
Une entreprise transporte des marchandises. Elle souhaite maximiser son profit en
optimisant le remplissage de ses moyens de transport. On considère qu’un moyen de
transport est limité par son volume (exprimé en litres). Chaque marchandise est
caractérisée par son prix (en euros) et son volume indivisible (en litres).
Supposons qu’on ait trois marchandises caractérisées par les couples (prix, volume)
suivants : 𝑚𝑚1 =(100,10), 𝑚𝑚2 =(100,10) et 𝑚𝑚3 =(250,20). Si le moyen de transport
peut encore charger 25 litres, il vaut mieux charger la marchandise numéro 3 qui
rapporte 250 € à l’entreprise plutôt que charger les marchandises numéros 2 et 3 qui
rapportent 200 € au total pour le même espace utilisé.
Partie A – Quelques outils
Nous souhaitons définir une classe Marchandise dont chaque instance définit une
marchandise possédant deux attributs entiers prix et volume.
Compléter le constructeur qui renvoie un objet Marchandise. Utiliser le mot-clé
assert afin qu’une exception soit levée si le paramètre v n’est pas strictement
positif.
On rappelle que si condition est une expression Python booléenne s’évaluant
à True ou False, l’instruction assert condition déclenche une exception
quand la condition s’évalue à False.
Donner une instruction qui permet de créer une variable m1 représentant une
marchandise d’un volume de 7 litres coûtant 20 €.
Proposer une méthode ratio(self) -> float qui renvoie le ratio
prix/volume d’une marchandise.
Proposer une fonction prixListe(tab: list) -> int qui renvoie le prix
cumulé de l’ensemble des marchandises formant le tableau tab.
Partie B – Première approche de rangement
Le transporteur souhaite maximiser son profit. On considère que nous avons les quatre marchandises définies par les couples (prix, volume) suivants :
𝑚𝑚1 =(40,20), 𝑚𝑚2 =(210,70), 𝑚𝑚3 =(160,40) et 𝑚𝑚4 =(50,50).
Préciser toutes les combinaisons de marchandises possibles si on ne dépasse
pas un volume de 100 litres et le prix associé. En déduire la combinaison de
marchandises qui maximise le prix.
Une première méthode appelée ChargementGlouton consiste à trier les
marchandises dans l’ordre décroissant de leur prix volumique (ratio prix/volume), puis transporter en priorité les marchandises avec le plus grand prix volumique. Si une marchandise est trop volumineuse pour être transportée, on essaie avec la
marchandise ayant le prix volumique juste inférieur, ce jusqu’à ce qu’aucune
marchandise ne puisse rentrer. Ainsi, en notant v_restant le volume disponible et
m_i la $(𝑖 +1)^e$ marchandise une fois les marchandises triées, l’algorithme peut s’écrire:
ChargementGlouton
n = nombre de marchandises
POUR i ALLANT de 0 à n-1 FAIRE
| SI volume de m_i <= v_restant ALORS
| | charger m_i
| | v_restant = v_restant - volume de m_i
TRANSPORTER le chargement prévu
Le tri dans l’ordre décroissant des prix volumiques donne 𝑚𝑚3 , 𝑚𝑚2, 𝑚𝑚1, 𝑚𝑚4. Si le moyen de transport accepte 100 litres de chargement, l’algorithme charge 𝑚𝑚3 et 𝑚𝑚1 pour un prix de 200 € (à comparer avec la combinaison trouvée précédemment pour maximiser le prix).
Par la suite, on rappelle que dans l’implémentation Python, les marchandises sont
définies par des instances de la classe Marchandise.
On donne quelques qualificatifs : dichotomique, glouton, graphique, insertion,
maximum, récursif, tri.
Indiquer, sans justification, le qualificatif qui s’applique le mieux à l’algorithme précédent.
Recopier et compléter la fonction tri(tab: list) -> None ci-dessous afin
qu’elle trie en place un tableau contenant des objets de type Marchandise selon
l’ordre décroissant des ratios. Ainsi, tab[0] doit contenir la marchandise avec
le plus haut ratio prix/volume après l’appel tri(tab).
Sans justifier, préciser le nom de ce tri, ainsi que son coût temporel dans le pire des cas (constant, logarithmique, linéaire, quasi-linéaire (𝑛𝑛 log2 𝑛𝑛), quadratique, cubique ou exponentiel).
Recopier et compléter la fonction charge suivante qui applique l’algorithme
ChargementGlouton décrit plus haut.
L’algorithme précédent ne renvoie pas toujours une solution optimale. On peut donc
suivre un algorithme récursif. On note n le nombre de marchandises et on souhaite
implémenter la fonction récursive chargeOptimale d’entête :
chargeOptimale(tab: list, v_restant: int, i: int) -> list
Un appel à cette fonction doit permettre de calculer la charge optimale pour un
transport de volume v_restant utilisant les marchandises à partir de l’indice i :
si i >= n, toutes les marchandises ont été essayées et il n’en reste plus
d’autres disponibles. L’appel récursif renvoie la liste vide ;
si i < n et la marchandise d’indice i est de volume strictement supérieur au
volume restant, l’appel récursif renvoie le résultat de l’appel effectué avec le
même volume restant mais avec la marchandise suivante, c’est-à-dire
chargeOptimale(tab, v_restant, i+1) ;
si i < n et la marchandise d’indice i est de volume inférieur ou égal au
volume restant, il existe deux options possibles :
– Option 1 soit on utilise la marchandise i, auquel cas le chargement
contiendra cette marchandise et celles du résultat de l’appel récursif à
partir de la prochaine marchandise et d’un volume restant strictement
inférieur,
– Option 2 soit on n’utilise pas la marchandise i, auquel cas le chargement
sera le résultat de l’appel récursif avec le même volume restant mais à
partir de la marchandise suivante.
On garde l’option de chargement qui maximise le prix transporté.
Compléter le code de la fonction chargeOptimale dont le principe a été décrit
ci-avant.
Principaux thèmes abordés : algorithmique (recherche dichotomique) et langages et programmation (récursivité)
dichotomierécursivitécomplexité
On veillera à mettre sur la copie toutes les réponses.
Partie A : La recherche dichotomique
1. La recherche d’un élément dans un tableau avec une méthode dichotomique ne peut se faire que si le tableau est trié.
a. Vrai
b. Faux
2. Le coût d’un algorithme de recherche dichotomique est :
a. Constant : Complexité O(1)
b. Linéaire : Complexité O(n)
c. Logarithmique : Complexité O(log(n))
3. Justifier pourquoi l’entier fin–deb est un variant de boucle qui montre la
terminaison du programme de recherche dichotomique de l’annexe 1 de l’exercice 2.
Partie B : La recherche dichotomique itérative
Le programme de recherche dichotomique de l’annexe 1 de l’exercice 2 est utilisé pour effectuer des recherches dans une liste.
Dans l’ensemble de cette partie, on considère la liste :
1. Expliquer pourquoi en ligne 2, on a «fin = len(liste)-1» plutôt que «fin = 6».
2. En Python, l’opérateur // donne le quotient de la division euclidienne de deux nombres entiers. Proposer un algorithme pour obtenir ce quotient.
3. Donner la trace complète de l’exécution rechercheDicho("lea", Lnoms) en
complétant le tableau ci-dessous sur votre copie :
Debut
Fin
M
condition deb <= fin
valeur renvoyée
4. Sur votre copie, modifier le code du corps de la fonction rechercheDicho() pour qu’elle renvoie aussi la position (indice) de l’élément cherché ou -1 si l’élément n’est pas trouvé.
On pourra indiquer sur la copie le numéro des lignes modifiées, à supprimer ou à
insérer s’il y a lieu.
Partie C : La recherche dichotomique récursive
1. Donner la définition d’une fonction récursive en programmation.
2. Écrire en langage naturel ou en python, l’algorithme de recherche dichotomique d’un élément dans une liste, triée de façon croissante, en utilisant une méthode récursive.
Il renverra True si l’objet a été trouvé, False sinon.
ANNEXE 1
On considère la fonction de recherche dichotomique suivante :
defrechercheDicho(elem,liste):"""
Cette fonction indique si un élément se trouve dans un
tableau.
Elle utilise la méthode de recherche dichotomique.
Elle prend en arguments :
- elem : élément à rechercher de type string
- liste : liste d'éléments de type string triée
par ordre croissant
Elle renvoie un booléen correspondant à la présence ou
non de l'élément
"""deb=0fin=len(liste)-1m=(deb+fin)//2whiledeb<=fin:ifliste[m]==elem:returnTrueelifliste[m]>elem:fin=m-1else:deb=m+1m=(deb+fin)//2returnFalse
Sujet Métropole Sept 2 2021 Exercice 4
Cet exercice porte sur la programmation en général et la récursivité en particulier.
tableaupermutationrécursivité
On s’intéresse dans cet exercice à un algorithme de mélange des éléments d’une liste.
Pour la suite, il sera utile de disposer d’une fonction echange qui permet d’échanger dans une liste lst les éléments d’indice i1 et i2.
Expliquer pourquoi le code Python ci-dessous ne réalise pas cet échange et en proposer une modification.
La documentation du module random de Python fournit les informations ci-dessous concernant la fonction randint(a,b) :
Renvoie un entier aléatoire N tel que a <= N <= b.
Parmi les valeurs ci-dessous, quelles sont celles qui peuvent être renvoyées par l’appel randint(0, 10) ?
0 1 3.5 9 10 11
Le mélange de Fischer Yates est un algorithme permettant de permuter
aléatoirement les éléments d’une liste. On donne ci-dessous une mise en œuvre récursive de cet algorithme en Python.
a. Expliquer pourquoi la fonction melange se termine toujours.
b. Lors de l’appel de la fonction melange, la valeur du paramètre ind doit être égale au plus grand indice possible de la liste lst.
Pour une liste de longueur n, quel est le nombre d’appels récursifs de la fonction melange effectués, sans compter l’appel initial ?
c. On considère le script ci-dessous :
lst=[vforvinrange(5)]melange(lst,4)
On suppose que les valeurs successivement renvoyées par la fonction
randint sont 2, 1, 2 et 0.
Les deux premiers affichages produits par l’instruction print(lst) de la fonction melange sont :
[0,1,2,3,4][0,1,4,3,2]
Donner les affichages suivants produits par la fonction melange.
d. Proposer une version itérative du mélange de Fischer Yates.
architecture
Bac 2022 Polynesie: Exercice 2
Cet exercice traite du thème « architecture matérielle », et principalement d’ordonnancement et d’expressions booléennes.
ordonnancementlogique
Un système est composé de 4 périphériques, numérotés de 0 à 3, et d’une mémoire, reliés entre eux par un bus auquel est également connecté un dispositif ordonnanceur.
À l’aide d’un signal spécifique envoyé sur le bus, l’ordonnanceur sollicite à tour de rôle les périphériques pour qu’ils indiquent le type d’opération (lecture ou écriture) qu’ils souhaitent effectuer, et l’adresse mémoire concernée.
Un tour a lieu quand les 4 périphériques ont été sollicités. Au début d’un nouveau tour, on considère que toutes les adresses sont disponibles en lecture et écriture.
Si un périphérique demande l’écriture à une adresse mémoire à laquelle on n’a pas encore accédé pendant le tour, l’ordonnanceur répond “OK” et l’écriture a lieu.
Si on a déjà demandé la lecture ou l’écriture à cette adresse, l’ordonnanceur répond “ATT” et l’opération n’a pas lieu.
Si un périphérique demande la lecture à une adresse à laquelle on n’a pas encore accédé en écriture pendant le tour, l’ordonnanceur répond “OK” et la lecture a lieu.
Plusieurs lectures peuvent avoir donc lieu pendant le même tour à la même adresse.
Si un périphérique demande la lecture à une adresse à laquelle on a déjà accédé en écriture, l’ordonnanceur répond “ATT” et la lecture n’a pas lieu.
Ainsi, pendant un tour, une adresse peut être utilisée soit une seule fois en écriture, soit autant de fois qu’on veut en lecture, soit pas utilisée.
Si un périphérique ne peut pas effectuer une opération à une adresse, il demande la même opération à la même adresse au tour suivant.
Question 1
Le tableau donné en annexe 1 indique, sur chaque ligne, le périphérique
sélectionné, l’adresse à laquelle il souhaite accéder et l’opération à effectuer sur cette adresse. Compléter dans la dernière colonne de cette annexe, à rendre avec la copie, la réponse donnée par l’ordonnanceur pour chaque opération.
On suppose dans toute la suite que :
le périphérique 0 écrit systématiquement à l’adresse 10 ;
le périphérique 1 lit systématiquement à l’adresse 10 ;
le périphérique 2 écrit alternativement aux adresses 11 et 12 ;
le périphérique 3 lit alternativement aux adresses 11 et 12 ;
Pour les périphériques 2 et 3, le changement d’adresse n’est effectif que lorsque l’opération et réalisée.
Question 2
On suppose que les périphériques sont sélectionnés à chaque tour dans l’ordre
0 ; 1 ; 2 ; 3. Expliquer ce qu’il se passe pour le périphérique 1.
Les périphériques sont sollicités de la manière suivante lors de quatre tours successifs :
au premier tour, ils sont sollicités dans l’ordre 0 ; 1 ; 2 ; 3 ;
au deuxième tour, dans l’ordre 1 ; 2 ; 3 ; 0 ;
au troisième tour, 2 ; 3 ; 0 ; 1 ;
puis 3 ; 0 ; 1 ; 2 au dernier tour.
Et on recommence…
Question 3
A. Préciser pour chacun de ces tours si le périphérique 0 peut écrire et si le
périphérique 1 peut lire.
B. En déduire la proportion des valeurs écrites par le périphérique 0 qui sont
effectivement lues par le périphérique 1.
On change la méthode d’ordonnancement : on détermine l’ordre des périphériques au cours d’un tour à l’aide de deux listes d’attente ATTL_L et ATT_E établies au tour précédent.
Au cours d’un tour, on place dans la liste ATT_L toutes les opérations de lecture mises en attente, et dans la liste d’attente ATT_E toutes les opérations d’écriture mises en attente.
Au début du tour suivant, on établit l’ordre d’interrogation des périphériques en procédant ainsi :
on interroge ceux présents dans la liste ATT_L, par ordre croissant d’adresse,
on interroge ensuite ceux présents dans la liste ATT_E, par ordre croissant
d’adresse,
puis on interroge les périphériques restants, par ordre croissant d’adresse.
Question 4
Compléter et rendre avec la copie le tableau fourni en annexe 2, en utilisant
l’ordonnancement décrit ci-dessus, sur 3 tours.
Les colonnes e0 et e1 du tableau suivant recensent les deux chiffres de l’écriture binaire de l’entier n de la première colonne.
nombre n
écriture binaire de n sur deux bits
e1
e0
0
00
0
0
1
01
0
1
2
10
1
0
3
11
1
1
L’ordonnanceur attribue à deux signaux sur le bus de données les valeurs de e0 et e1 associées au numéro du circuit qu’il veut sélectionner. On souhaite construire à l’aide des portes ET, OU et NON un circuit pour chaque périphérique.
Chacun des quatre circuits à construire prend en entrée deux signaux e0 et e1, le signal de sortie s valant 1 uniquement lorsque les niveaux de e0 et e1 correspondent aux bits de l’écriture en binaire du numéro du périphérique correspondant.
Par exemple, le circuit ci-dessous réalise la sélection du périphérique 3. En effet, le signal s vaut 1 si et seulement si e0 et e1 valent tous les deux 1.
470 × 138
Question 5
A. Recopier sur la copie et indiquer dans le circuit ci-dessous les entrées e0 et e1 de façon à ce que ce circuit sélectionne le périphérique 1.
566 × 170
B. Dessiner un circuit constitué d’une porte ET et d’une porte NON, qui
sélectionne le périphérique 2.
c. Dessiner un circuit permettant de sélectionner le périphérique 0.
1252 × 590
1252 × 788
bac 2021 candidat libre exercice 3
cmd unix
La commande UNIX ps présente un cliché instantané des processus en cours d’exécution.
Avec l’option −eo pid,ppid,stat,command, cette commande affiche dans l’ordre l’identifiant du processus PID (process identifier), le PPID (parent process identifier), l’état STAT et le nom de la commande à l’origine du processus.
Les valeurs du champ STAT indique l’état des processus :
R : processus en cours d’exécution
S : processus endormi
Sur un ordinateur, on exécute la commande ps −eo pid,ppid,stat,command et on obtient un affichage dont on donne ci-dessous un extrait:
À l’aide de cet affichage, répondre aux questions ci-dessous.
Quel est le nom de la première commande exécutée par le système d’exploitation lors du démarrage?
Quels sont les identifiants des processus actifs sur cet ordinateur au moment de l’appel de la commande ps? Justifier la réponse.
Depuis quelle application a-t-on exécuté la commande ps? Donner les autres commandes qui ont été exécutées à partir de cette application.
Expliquer l’ordre dans lequel les deux commandes python programme1.py et python programme2.py ont été exécutées.
Peut-on prédire que l’une des deux commandes python programme1.py et python programme2.py finira avant l’autre?
bac 2021 candidat libre exercice 2 sujet 2
ordonnancement
Les états possibles d’un processus sont : prêt, élu, terminé et bloqué.
Expliquer à quoi correspond l’état élu.
Proposer un schéma illustrant les passages entre les différents états.
On suppose que quatre processus C₁, C₂, C₃ et C₄ sont créés sur un ordinateur, et qu’aucun autre processus n’est lancé sur celui-ci, ni préalablement ni pendant l’exécution des quatre processus.
L’ordonnanceur, pour exécuter les différents processus prêts, les place dans une structure de données de type file. Un processus prêt est enfilé et un processus élu est défilé.
Parmi les propositions suivantes, recopier celle qui décrit le fonctionnement des entrées/sorties dans une file :
Premier entré, dernier sorti
Premier entré, premier sorti
Dernier entré, premier sorti
On suppose que les quatre processus arrivent dans la file et y sont placés dans l’ordre C₁, C₂, C₃ et C₄.
Les temps d’exécution totaux de C₁, C₂, C₃ et C₄ sont respectivement 100 ms, 150 ms, 80 ms et 60 ms.
Après 40 ms d’exécution, le processus C₁ demande une opération d’écriture disque, opération qui dure 200 ms. Pendant cette opération d’écriture, le processus C₁ passe à l’état bloqué.
Après 20 ms d’exécution, le processus C₃ demande une opération d’écriture disque, opération qui dure 10 ms. Pendant cette opération d’écriture, le processus C₃ passe à l’état bloqué.
Sur la frise chronologique donnée en annexe (à rendre avec la copie), les états du processus C₂ sont donnés.
Compléter la frise avec les états des processus C₁, C₃ et C₄.
Annexe de l’exercice 2
On trouvera ci-dessous deux programmes rédigés en pseudo-code.
Verrouiller un fichier signifie que le programme demande un accès exclusif au fichier et l’obtient si le fichier est disponible.
Programme 1
Programme 2
Verrouiller fichier_1
Verrouiller fichier_2
Calculs sur fichier_1
Verrouiller fichier_1
Verrouiller fichier_2
Calculs sur fichier_1
Calculs sur fichier_1
Calculs sur fichier_2
Calculs sur fichier_2
Déverrouiller fichier_1
Calculs sur fichier_1
Déverrouiller fichier_2
Déverrouiller fichier_2
Déverrouiller fichier_1
En supposant que les processus correspondant à ces programmes s’exécutent simultanément (exécution concurrente), expliquer le problème qui peut être rencontré.
Proposer une modification du programme 2 permettant d’éviter ce problème.
BDD SQL
Bac 2024 Amerique du Nord: Exercice 3
Cet exercice porte sur le langage SQL et les bases de données.
sql
Un pharmacien nouvellement installé décide de créer son propre système de gestion
des médicaments qu’il délivre à ses clients.
Pour sa base de données relationnelle, il a déjà élaboré la première relation à l’aide
des données indiquées sur les cartes vitales de ses deux premiers clients :
La table des médicaments de son officine est présentée ci-dessous.
Écrire une requête SQL permettant d’afficher les noms de tous les médicaments
dont le prix est strictement inférieur à 3 euros.
Madame Martin présente au pharmacien une nouvelle ordonnance :
Ordonnance de Madame Sophie Martin.
Il saisit les informations de cette ordonnance dans la relation ordonnance, chaque médicament prescrit correspondant à un enregistrement dans la table ci-dessous.
Ecrire une requête SQL permettant d’ajouter les informations de la carte vitale
de sa troisième cliente présentée ci-dessous :
Image de la carte vitale extraite de la page wikipédia
Donner les attributs qui doivent être déclarés comme clés étrangères de la
relation ordonnance et en préciser l’utilité.
Indiquer, pour les lignes 7 et 8 de la table ordonnance, le nombre de boites prescrites.
Écrire la requête SQL mettant à jour la quantité du médicament Acide
ascorbique en stock dans l’officine du pharmacien suite au passage de Madame
Martin.
Calculer le coût total des médicaments fournis à Madame Martin (on ne
demande pas d’écrire une requête ici, mais de calculer le coût total en justifiant
le calcul).
Écrire la requête SQL permettant d’afficher le nom du médicament pour
l’ordonnance ayant l’id_ordo numéro 6.
Bac 2022 Polynesie: Exercice 3
Cet exercice traite du thème « base de données », et principalement du modèle
relationnel et du langage SQL.
sql
L’énoncé de cet exercice peut utiliser les mots du langage SQL suivants :
Un site web recueille des données de navigation dans une base de données afin
d’étudier les profils de ses visiteurs.
Chaque requête d’interrogation d’une page de ce site est enregistrée dans une première table dénommée Visites sous la forme d’un 5-uplet : (identifiant, adresse IP, date et heure de visite, nom de la page, navigateur).
Le chargement de la page index.html par 192.168.1.91 le 12 juillet 1998 à 22h48 aura par exemple été enregistré de la façon suivante :
(1534, "192.168.1.91", "1998-07-12 22:48:00", "index.html", "Internet explorer 4.1").
La commande SQL ayant permis de créer cette table est la suivante:
A. Donner une commande d’interrogation en langage SQL permettant d’obtenir
l’ensemble des 2-uplets (adresse IP, nom de la page) de cette table.
B. Donner une commande en langage SQL permettant d’obtenir l’ensemble des
adresses IP ayant interrogé le site, sans doublon.
C. Donner une commande en langage SQL permettant d’obtenir la liste des
noms des pages visitées par l’adresse IP 192.168.1.91
Ce site web met en place, sur chacune de ses pages, un programme en javascript qui envoie au serveur, à intervalle régulier de 15 secondes, le temps en secondes de présence sur la page. Ces envois contiennent tous la valeur de identifiant correspondant au chargement initial de la page.
Par exemple, si le visiteur du 12 juillet 1998 est resté 65 secondes sur la page, celle-ci a envoyé au serveur les 4 doublets (1534, 15), (1534, 30), (1534, 45) et (1534, 60).
Ces données sont enregistrées dans une table nommée Pings créée avec la
commande ci-dessous :
En plus de l’inscription d’une ligne dans la table Visites, chaque chargement d’une nouvelle page provoque l’insertion d’une ligne dans la table Pings comprenant l’identifiant de ce chargement et une durée de 0.
Les attributs identifiant des tables Visites et Pings partagent les mêmes
valeurs.
Question 2
A. De quelle table l’attribut identifiant est-il la clé primaire ?
B. De quelle table l’attribut identifiant est-il une clé étrangère ?
C. Par conséquent, quelles vérifications sont automatiquement effectuées par le système de gestion de base de données ?
Question 3
Le serveur reçoit le doublet (identifiant, duree) suivant : (1534, 105).
Écrire la commande SQL d’insertion qui permet d’ajouter cet enregistrement à la
table Pings.
On envisage ensuite d’optimiser la table en se contentant d’une seule ligne par
identifiant dans la table Pings : les valeurs de l’attribut duree devraient alors être mises à jour à chaque réception d’un nouveau doublet (identifiant, duree).
Question 4
A. Écrire la requête de mise à jour permettant de fixer à 120 la valeur de l’attribut duree associée à l’identifiant 1534 dans la table Pings.
B. Expliquer pourquoi on ne peut pas être certain que les données envoyées par
une page web, depuis le navigateur d’un client, via plusieurs requêtes formulées en javascript, arrivent au serveur dans l’ordre dans lequel elles ont été émises.
C. En déduire qu’il est préférable d’utiliser une requête d’insertion plutôt qu’une requête de mise à jour pour ajouter des données à la table Pings.
Question 5
Écrire une requête SQL utilisant le mot-clef JOIN et une clause WHERE,
permettant de trouver les noms de toutes les pages qui ont été consultées plus
d’une minute par au moins un utilisateur.
Bac 2022 metropole1: Exercice 2
Cet exercice porte sur les bases de données.
sql
On pourra utiliser les mots clés SQL suivants : SELECT, FROM, WHERE, JOIN, ON, INSERT, INTO, VALUES, UPDATE, SET, AND.
Nous allons étudier une base de données traitant du cinéma dont voici le schéma
relationnel qui comporte 3 relations :
la relation individu (id_ind, `nom, prenom, naissance)
la relation realisation (id_rea, titre, annee, type)
la relation emploi (id_emp, description, #id_ind, #id_rea)
Les clés primaires sont en gras et les clés étrangères sont précédées d’un #.
Ainsi emploi.id_ind est une clé étrangère faisant référence à individu.id_ind.
Voici un extrait des tables individu et realisation :
1310 × 330
Question 1
On s’intéresse ici à la récupération de données dans une relation.
a
A. Écrire ce que renvoie la requête ci-dessous :
B. Fournir une requête SQL permettant de récupérer le titre et la clé primaire de chaque film dont la date de sortie est strictement supérieure à 2020.
Question 2
Cette question traite de la modification de relations.
A. Dire s’il faut utiliser la requête 1 ou la requête 2 proposées ci-dessous pour modifier la date de naissance de Daniel Crog. Justifier votre réponse en
expliquant pourquoi la requête refusée ne pourra pas fonctionner.
B. Expliquer si la relation individu peut accepter (ou pas) deux individus
portant le même nom, le même prénom et la même date de naissance.
Question 3
Cette question porte sur la notion de clés étrangères.
A. Recopier sur votre copie les demandes ci-dessous, dans leur intégralité, et les compléter correctement pour qu’elles ajoutent dans la relation emploi les rôles de Daniel Crog en tant que James Bond dans le film nommé ‘Casino
Impérial’ puis dans le film ‘Ciel tombant’.
B. On désire rajouter un nouvel emploi de Daniel Crog en tant que James Bond
dans le film ‘Docteur Yes’.
Expliquer si l’on doit d’abord créer l’enregistrement du film dans la relation
realisation ou si l’on doit d’abord créer le rôle dans la relation emploi.
Question 4
Cette question traite des jointures.
A. Recopier sur votre copie la requête SQL ci-dessous, dans son intégralité, et la compléter de façon à ce qu’elle renvoie le nom de l’acteur, le titre du film et l’année de sortie du film, à partir de tous les enregistrements de la relation emploi pour lesquels la description de l’emploi est 'Acteur(James Bond)'.
B. Fournir une requête SQL permettant de trouver toutes les descriptions des
emplois de Denis Johnson (Denis est son prénom et Johnson est son nom).
On veillera à n’afficher que la description des emplois et non les films associés à ces emplois.
Exercice 2 25-NSIJ2ME1:
Cet exercice porte sur les bases de données relationnelles, le langage SQL et la
programmation.
sqlpythontableauxsqlite
Partie A
sql
Une ludothèque municipale a décidé de moderniser sa gestion en créant une base de
données informatique. Cette base de données permettra de suivre les jeux
disponibles, les emprunts effectués par les adhérents, ainsi que les avis laissés sur les
différents jeux. Pour commencer, quatre tables principales ont été identifiées : jeu, adhérent, emprunt et avis. Ces tables et leurs relations vont permettre de stocker toutes les informations essentielles au bon fonctionnement de la ludothèque. On va considérer que la ludothèque n’a qu’un exemplaire de chaque jeu (deux jeux de la ludothèque ne peuvent donc pas avoir le même nom).
La base de données de la ludothèque
Dans la figure ci-dessus, les clés primaires de chacune des tables sont soulignées et les clés étrangères sont précédées du symbole #.
Dans cet exercice, on pourra utiliser les clauses du langage SQL pour :
construire des requêtes d’interrogation à l’aide de SELECT, FROM, WHERE (avec les opérateurs logiques AND, OR) et JOIN ... ON ;
construire des requêtes d’insertion et de mise à jour à l’aide de UPDATE,
INSERT et DELETE;
affiner les recherches à l’aide de DISTINCT et ORDER BY;
réaliser des agrégations à l’aide de COUNT, SUM ou AVG.
Par exemple, l’instruction SQL suivante donne le nombre de jeux présents dans la table jeu:
SELECT COUNT(nomJeu) FROM jeu;
Expliquer pourquoi on ne peut pas prendre l’attribut nom comme clé primaire
pour la relation adherent.
Décrire ce que donne la requête SQL suivante :
SELECTnomJeu,editeurFROMjeuORDERBYnomJeu;
Lorsque qu’un jeu est emprunté et n’a pas encore été rendu, la valeur de l’attribut
dateRendu de la table emprunt est à NULL.
Écrire une requête permettant de connaitre le nom de tous les jeux qui sont en
cours d’emprunt.
Écrire une requête SQL pour afficher le nom et le prénom de tous les adhérents
qui ont emprunté le jeu “Catan”.
Claire VOYANT, adhérente de longue date à cette ludothèque, a emprunté le
jeu “Catan” et l’a rendu le 3 juin 2025. Lors de l’emprunt, la valeur de
id_emprunt était 1538.
Écrire une requête SQL qui a permis de mettre à jour la base de données afin
qu’elle prenne en compte que ce jeu a été rendu. Toutes les dates de la base
de données sont écrites sous le format 'AAAA-MM-JJ'.
Écrire une requête SQL qui permet de trouver le nom et la catégorie de tous les
jeux de la ludothèque sortis à partir de 2010 et dont l’âge minimum est
strictement inférieur à 10 ans.
On modifie la table avis pour ajouter une note (entier 0-5) pour chaque jeu à l’aide de l’attribut note.
Ecrire une requête sql qui calcule la moyenne des notes obtenues pour le jeu “Catan”.
La ludothèque décide d’organiser des événements. Pour cela, elle ajoute une relation
evenement à sa base de données. En outre, pour chaque événement, elle souhaite
garder en mémoire une trace des adhérents qui y ont participé. À cette fin, elle
complète sa base avec une relation participation.
La base de données de la ludothèque actualisée
Proposer les clés étrangères de la table participation en précisant le nom
des attributs auxquels elles font référence.
Proposer une requête qui identifie les adherants qui ont participé à l’evenement de nom “concours_pokemon”.
Ecrire la requête qui compte le nombre de participations par membre aux differents evenements (GROUP BY id_adherant), et retourne une liste ordonnée de manière décroissante de participations pour ces membres.
Partie B
pythontableauxsqlite
Le programme Python suivant permet de créer la liste de tous les jeux empruntés,
sachant que, dans celle-ci, un jeu va apparaître autant de fois qu’il a été emprunté.
importsqlite3# Connexion à la base de donnéesconnection=sqlite3.connect("ludotheque.db")# creation d'un curseur pour recuperer les donnees des requetescurseur=connection.cursor()# Exécution de la requêtecurseur.execute("SELECT nomJeu FROM emprunt")# Récupération des résultatsjeux=curseur.fetchall()liste=[]# Création de la liste des jeux empruntésforjeuinjeux:liste.append(jeu[0])# Fermeture de la connexioncurseur.close()connection.close()
Écrire un script Python permettant de créer le dictionnaire dict_emprunts qui,
à chaque jeu emprunté, associe le nombre de fois où il a été emprunté.
On veut créer un podium des jeux les plus souvent empruntés. Comme il peut y avoir
des égalités à la première, deuxième ou troisième place, il peut y avoir plus de trois jeux sélectionnés sur le podium.
Par exemple, si le dictionnaire des emprunts est :
Proposer un script Python permettant de générer ce podium.
securite
Bac 2021 Centres étrangers 2: Exercice 3
Thèmes abordés : conversion décimal/binaire, table de vérité, codage des caractères
binairelogiqueasciixorchiffrement
L’objectif de l’exercice est d’étudier une méthode de cryptage d’une chaîne de
caractères à l’aide du codage ASCII et de la fonction logique XOR.
1. Le nombre 65, donné ici en écriture décimale, s’écrit 01000001 en notation
binaire. En détaillant la méthode utilisée, donner l’écriture binaire du nombre
89.
2. La fonction logique OU EXCLUSIF, appelée XOR et représentée par le symbole
$\bigoplus$, fournit une sortie égale à 1 si l’une ou l’autre des deux entrées vaut 1 mais
pas les deux.
On donne ci-contre la table de vérité de la fonction XOR:
Si on applique cette fonction à un nombre codé en binaire, elle opère bit à bit.
Poser et calculer l’opération : $11001110 \bigoplus 01101011$
3. On donne, ci-dessous, un extrait de la table ASCII qui permet d’encoder les
caractères de A à Z.
On peut alors considérer l’opération XOR entre deux caractères en effectuant
le XOR entre les codes ASCII des deux caractères. Par exemple : ‘F’ XOR ‘S’
sera le résultat de $01000110 \bigoplus 01010011$.
On souhaite mettre au point une méthode de cryptage à l’aide de la fonction
XOR.
Pour cela, on dispose d’un message à crypter et d’une clé de cryptage de même
longueur que ce message. Le message et la clé sont composés uniquement
des caractères du tableau ci-dessus et on applique la fonction XOR caractère
par caractère entre les lettres du message à crypter et les lettres de la clé de
cryptage.
Par exemple, voici le cryptage du mot ALPHA à l’aide de la clé YAKYA :
Ecrire une fonction xor_crypt(message, cle) qui prend en paramètres deux
chaînes de caractères et qui renvoie la liste des entiers correspondant au
message crypté.
Aide :
On pourra utiliser la fonction native du langage Python ord(c) qui prend en paramètre un caractère c et qui renvoie un nombre représentant le code ASCII du caractère c.
On considère également que l’on dispose d’une fonction écrite xor(n1,n2) qui prend en paramètre deux nombres n1 et n2 et qui renvoie le résultat de n1 ⊕ n2.
4. On souhaite maintenant générer une clé de la taille du message à partir d’un
mot quelconque. On considère que le mot choisi est plus court que le
message, il faut donc le reproduire un certain nombre de fois pour créer une
clé de la même longueur que le message.
Par exemple, si le mot choisi est YAK pour crypter le message ALPHABET, la
clé sera YAKYAKYA.)
Créer une fonction generer_cle(mot,n) qui renvoie la clé de longueur n à partir de la chaîne de caractères mot.
5. Recopier et compléter la table de vérité de $(𝑬𝟏 \bigoplus 𝑬𝟐) \bigoplus 𝑬𝟐$.
A l’aide de ce résultat, proposer une démarche pour décrypter un message crypté.
Exercice 3 25-NSIJ2ME1
Cet exercice porte sur la programmation de base en Python, la sécurisation des
communications et les réseaux.
python baseslogiquechiffrementhttps
Partie A - La méthode du masque jetable
Dans cette partie, on s’intéresse à une méthode de chiffrement dite du masque jetable.
Voici ce que l’on peut lire sur le site Wikipédia :
Le chiffrement par la méthode du masque jetable consiste à combiner le message en
clair avec une clé présentant les caractéristiques très particulières suivantes :
la clé doit être une suite de caractères au moins aussi longue que le message
à chiffrer ;
les caractères composant la clé doivent être choisis de façon totalement
aléatoire ;
chaque clé, ou « masque », ne doit être utilisée qu’une seule fois (d’où le nom
de masque jetable).
Illustrons cette méthode par un exemple : on souhaite chiffrer le message HELLO avec
la clé aléatoire, ou « masque », WMCKL.
Pour cela, on attribue un nombre à chaque lettre, par exemple le rang dans l’alphabet, de 0 à 25.
Lettre
A
B
C
D
E
F
G
H
I
J
…
Y
Z
Rang
0
1
2
3
4
5
6
7
8
9
…
24
25
Ensuite, on additionne la valeur du rang de chaque lettre du message avec la valeur
du rang correspondante dans le masque.
Enfin, si le résultat est supérieur à 25 on soustrait 26 (calcul dit « modulo 26 »).
Ainsi, le chiffrement du message HELLO avec la clé WMCKL donne le message chiffré
DQNVZ comme le montre l’illustration suivante.
Exemple de chiffrement par la méthode du masque jetable - wikipedia
Dans cet exercice, on ne travaillera que sur des chaînes de caractères écrites en
majuscules non accentuées (les 26 caractères allant de ‘A’ à ‘Z’).
Chiffrer, par la méthode du masque jetable, le message LIBRE à l’aide de la clé
EYQMT.
En Python, on crée une fois pour toute la variable alphabet qui sera accessible et
utilisable dans toutes les fonctions. Celle-ci contient la liste des 26 lettres de l’alphabet rangées dans l’ordre alphabétique :
Écrire une fonction Python indice qui prend pour paramètre une liste L et
renvoie l’indice de element dans la liste L.
On supposera que chaque élément de la liste L n’y apparaît qu’une seule fois
et que element est bien présent dans la liste L.
Par exemple, l’appel indice(alphabet, 'K') renvoie l’entier 10.
Écrire une fonction Python lettres_vers_indices qui prend pour
paramètre une chaîne de caractères et renvoie, dans l’ordre, la liste des indices
de ces caractères dans l’alphabet. Par exemple, l’appel lettres_vers_indices('HELLO') renvoie la liste d’entiers [7, 4, 11, 11, 14].
On dispose également d’une fonction indices_vers_lettres, qu’on ne demande
pas d’écrire, permettant de convertir une liste d’entiers, compris entre 0 et 25, en une chaîne de caractères.
Par exemple, l’appel indices_vers_lettres([3, 16, 13, 21, 25]) renvoie
la chaîne de caractères ‘DQNVZ’.
Ci-après, on donne une fonction Python chiffrement incomplète, qui, à partir d’un
message msg et d’une clé cle entrés en paramètres, renvoie la chaîne de caractères représentant le message chiffré par la méthode du masque jetable.
Recopier et compléter les lignes 7 à 13 de la fonction chiffrement.
Indiquer, en justifiant, ce que l’on observe lors de l’appel
chiffrement('RESEAU', 'GFTZ').
On s’intéresse maintenant au déchiffrement d’un message chiffré par la méthode du
masque jetable.
Par exemple, le déchiffrement du message DQNVZ avec la clé WMCKL donne le
message HELLO.
Déchiffrer le message GMEDH avec la clé FVEIT.
Expliquer comment procéder pour déchiffrer un message lorsqu’on connaît la
clé.
On souhaite maintenant écrire, en Python, une fonction dechiffrement qui permet
de déchiffrer un message chiffré par la méthode du masque jetable.
Pour cela, on s’inspire de la fonction chiffrement dans laquelle les paramètres ainsi que les lignes 2 à 5 sont inchangées. On décide cependant de remplacer, ligne 6, le nom de la variable indices_msg_chiffre par le nom plus explicite
indices_msg_dechiffre.
8. Adapter les lignes 6 à 13 de la fonction chiffrement pour obtenir la nouvelle
fonction dechiffrement.
Partie B - Sécurisation des communications
Expliquer la différence entre un algorithme de chiffrement symétrique et un
algorithme de chiffrement asymétrique.
Alice souhaite envoyer un message à Bob par l’intermédiaire d’un réseau informatique
en utilisant un algorithme de chiffrement asymétrique.
Pour cela, Bob envoie à Alice sa clé publique. Alice chiffre ensuite le message à l’aide de la clé publique de Bob qu’elle vient de recevoir, puis elle envoie ce message chiffré à Bob.
Indiquer comment Bob peut déchiffrer le message que lui envoie Alice.
Expliquer comment une tierce personne pourrait se faire passer pour Alice sans
que Bob ne s’en aperçoive.
Expliquer brièvement le fonctionnement du protocole HTTPS.
Expliquer pourquoi, pour sécuriser intégralement les communications sur
Internet, on utilise le protocole HTTPS plutôt qu’un chiffrement asymétrique.
reseaux
Exercice 3 25-NSIJ2ME1
binairemasquelogiqueping
Partie C - Réseaux
Bob et Marc travaillent pour une petite compagnie d’assurances.
Leurs postes de travail font partie d’un même réseau local géré par l’administratrice système qui dispose du bloc d’adresses IPv4 192.168.110.0/24.
La notation /24 situé à la suite de l’adresse 192.168.110.0 signifie que le masque de sous-réseau du réseau de cette entreprise est 255.255.255.0 :
les trois premiers octets d’une adresse IP sur ce réseau permettent donc d’identifier la partie réseau de l’adresse, alors que le dernier octet permet d’identifier la partie hôte et est propre à chaque machine sur le réseau.
Ce sous-réseau permet donc d’attribuer 256 adresses
IPv4 différentes.
L’administratrice choisit alors d’attribuer, en représentation décimale, l’identifiant 115 pour la partie hôte du poste de travail de Bob et l’identifiant 153 pour celui de Marc.
Depuis son poste de travail, Marc souhaite tester la communication avec celui de Bob.
Pour cela, il exécute la commande ping 192.168.100.115 et obtient l’affichage
suivant :
Expliquer l’affichage obtenu et corriger l’erreur de Marc.
Afin d’améliorer les performances et la sécurité du réseau de l’entreprise,
l’administratrice système décide de séparer le réseau local en plusieurs sous-réseaux et de les relier entre eux par des routeurs. Pour cela, elle modifie le masque de sous-réseau qui devient 11111111.11111111.11111111.11100000, donné ici en représentation binaire.
Donner la représentation décimale de ce masque de sous-réseau.
Pour obtenir l’adresse IPv4 du sous-réseau auquel appartient une machine, il suffit
d’appliquer l’opérateur binaire ET, bit à bit, entre le masque de sous-réseau et
l’adresse IPv4 de la machine.
Par exemple, prenons le dernier octet de l’adresse IPv4 de Bob dont la représentation binaire est 01110011 : en appliquant bit à bit l’opérateur binaire ET entre cet octet et l’octet correspondant dans le masque, on obtient le dernier octet de l’adresse du sous-
réseau, soit 01100000.
Le poste de travail de Bob est donc sur le sous-réseau d’adresse 192.168.110.96.
Indiquer le nombre total d’adresses IPv4 pouvant être attribuées sur le sous-
réseau d’adresse 192.168.110.96 sur lequel se trouve Bob.
L’administratrice système attribue maintenant l’adresse IPv4 192.168.110.134 au
poste de travail de Zoé, nouvelle employée de la compagnie d’assurances.
Donner la représentation binaire du nombre 134.
Depuis son poste de travail, Zoé exécute les deux commandes suivantes :
commande n°1 : ping 192.168.110.115 ;
commande n°2 : ping 192.168.110.153.
Indiquer, en justifiant, laquelle de ces deux commandes a produit l’affichage :
4 packets transmitted, 4 received, 0% packet loss, time
3002ms
Bac 2022 Metropole1: Exercice 3
Cet exercice porte sur les représentations binaires et les protocoles de routage.
binaireroutageroutage
Question 1
Une adresse IPv4 est représentée sous la forme de 4 nombres séparés par des
points. Chacun de ces 4 nombres peut être représenté sur un octet.
A. Donner en écriture décimale l’adresse IPv4 correspondant à l’écriture binaire :
11000000.10101000.10000000.10000011
B. Tous les ordinateurs du réseau A ont une adresse IPv4 de la forme :
192.168.128._ _ _ , où seul le dernier octet (représenté par _ _ _ ) diffère.
Donner le nombre d’adresses différentes possibles du réseau A.
Question 2
On rappelle que le protocole RIP cherche à minimiser le nombre de routeurs
traversés (qui correspond à la métrique). On donne les tables de routage d’un
réseau informatique composé de 5 routeurs (appelés A, B, C, D et E), chacun
associé directement à un réseau du même nom obtenues avec le protocole RIP :
1234 × 916
A. Donner la liste des routeurs avec lesquels le routeur A est directement
relié.
B. Représenter graphiquement et de manière sommaire les 5 routeurs
ainsi que les liaisons existantes entre ceux-ci.
Question 3
Le protocole OSPF est un protocole de routage qui cherche à minimiser la
somme des métriques des liaisons entre routeurs.
Dans le protocole de routage OSPF le débit des liaisons entre routeurs agit
sur la métrique via la relation : $metrique = \tfrac{10^8}{debit}$ dans laquelle le débit est exprimé en bit par seconde (bps).
On rappelle qu’un kbps est égal à $10^3$ bps et qu’un Mbps est égal à $10^6$ bps.
A. Recopier sur votre copie et compléter le tableau suivant :
Débit
100 kbps
500 kbps
?
100 Mbps
Métrique associé
1000
?
10
1
1230 × 644
Les nombres présents sur les liaisons représentent les coûts des routes avec le
protocole OSPF.
B. Indiquer le chemin emprunté par un message d’un ordinateur du réseau F à
destination d’un ordinateur du réseau I.
Justifier votre réponse.
C. Recopier et compléter la table de routage du routeur F.
D. Citer une unique panne qui suffirait à ce que toutes les données des échanges de tout autre réseau à destination du réseau F transitent par le routeur G.
Expliquer en détail votre réponse.
Question 4 (sup hors bac)
A. Donner les caractéristiques du graphe de réseaux schématisé plus haut.
On donne cette fois le tableau constitué à partir de l’algorithme de Dijkstra, appliqué à ce même graphe de reseaux:
le colonnes représentent les sommets à atteindre
les lignes sont les sommets de départ
On renseigne dans les cases la distance cumulée depuis le noeud F, jusqu’au noeud de la colonne, en passant par le noeud adjacent de la ligne. Par exemple, I peut être atteint en venant du noeud K avec une longueur de 13.
G
H
I
J
K
L
F
5
G
H
6
I
J
8
8
11
K
13
L
B. Représenter le graphe des chemins pour explorer depuis F les autres noeuds, en suivant le chemin le plus court.
C. Ce graphe représente l’arbre couvrant du graphe. Donner les caractéristiques de cet arbre.
D. Quel est le chemin le plus court pour aller de F à G?
E. Même question, mais cette fois pour aller de H à K.
bac 2024 metropole1 exercice 2
Cet exercice traite de protocoles de routage, de sécurité des communications et de
base de données relationnelle.
routage
Une agence de voyage propose des croisières en bateau. Chaque croisière a un nom
unique et passe par quatre escales correspondant à des villes qui ont elles aussi des noms différents.
Pour gérer les réservations de ses clients, l’agence utilise une base de données.
Partie A
L’agence de voyage possède deux bureaux distincts.
Elle passe par un prestataire de service qui héberge sa base de données et utilise un système de gestion de base de données relationnelle.
Vous trouverez ci-après un schéma du réseau entre les deux bureaux de l’agence de
voyage et le prestataire.
On peut y voir les différents routeurs (nommés de A à I) ainsi que le coût des liaisons entre eux.
Topologie du réseau
Donner deux services rendus par un système de gestion de bases de données
relationnelles.
Le protocole RIP (Routing Information Protocol) est un protocole de routage qui
minimise le nombre de routeurs par lesquels les paquets transitent.
Le protocole OSPF (Open Shortest Path First) est un protocole de routage qui
minimise le coût du transit des paquets. Ce coût s’evalue grâce à la loi:
$$cout = \tfrac{18^8}{Debit}$$
Donner la route suivie par une requête issue du bureau numéro 1 jusqu’au
prestataire si on utilise le protocole RIP.
Le debit d’une liaison, utilisé pour le calcul du coût, s’exprime en bits par seconde. Donner une définition de ce qu’est le débit
Calculer le coût pour une liaison de débit 100 Mb par s. (fast ethernet)
Donner les deux routes que pourrait suivre une requête issue du bureau numéro
2 jusqu’au prestataire si on utilise le protocole OSPF. Donner le coût de chaque
route.
Bac 2024 Amerique du Nord J2 exercice 3
Cet exercice porte sur la programmation objet, les structures de données, les réseaux
et l’architecture matérielle.
pooadresses ipblockchain
On considère un réseau local constitué des trois machines de Alice, Bob et Charlie
dont les adresses IP sont les suivantes :
la machine d’Alice a pour adresse 192.168.1.1 ;
la machine de Bob a pour adresse 192.168.1.2.
On rappelle que l’adresse 192.168.1.255 est l’adresse de diffusion qui sert à communiquer avec toutes les machines du réseau local et le masque de ce réseau local est 255.255.255.0. Cette adresse de diffusion est réservée et ne peut être attribuée à une machine.
Partie A
Donner une adresse IP possible pour la machine de Charlie afin qu’elle puisse communiquer avec celles d’Alice et Bob dans le réseau local. Justifier votre réponse en donnant toutes les conditions à respecter dans le choix de cette adresse IP.
Ce réseau est utilisé pour effectuer des transactions financières en monnaie numérique nsicoin entre les trois utilisateurs. Pour cela, on crée la classe Transaction ci-dessous :
Toutes les dix minutes, les transactions réalisées pendant cet intervalle de temps sont regroupées par ordre d’apparition dans une liste Python. Dans un intervalle de dix minutes, Alice envoie dix nsicoin à Charlie puis Bob envoie cinq nsicoin à Alice. Écrire la liste Python correspondante à ces transactions.
Pour garder une trace de toutes les transactions effectuées, on utilise une liste chaînée de blocs (ou blockchain) dont le code Python est fourni ci-dessous. Toutes les dix minutes un nouveau bloc contenant les nouvelles transactions est créé et ajouté à la blockchain.
classBloc:def__init__(self,liste_transactions,bloc_precedent):self.liste_transactions=liste_transactionsself.bloc_precedent=bloc_precedent# de type BlocclassBlockchain:def__init__(self):self.tete=self.creer_bloc_0()defself.creer_bloc_0(self):"""
Crée le premier bloc qui distribue 100 nsicoin à tous les utilisateurs
(un pseudo-utilisateur Genesis est utilisé comme
expéditeur)
"""liste_transactions=[Transaction("Genesis","Alice",100),Transaction("Genesis","Bob",100),Transaction("Genesis","Charlie",100)]returnBloc(liste_transactions,None)
La figure 1 représente les trois premiers blocs d’une Blockchain. Expliquer pourquoi la valeur de l’attribut bloc_precedent du bloc0 est None.
Blockchain
À l’aide des classes Bloc et Blockchain, écrire le code Python permettant de créer un objet ma_blockchain de type Blockchain représenté par la figure 1.
Donner le solde en nsicoin de Bob à l’issue du bloc2.
On souhaite doter la classe Blockchain d’une méthode ajouter_bloc qui prend en paramètre la liste des transactions des dix dernières minutes et l’ajoute dans un nouveau bloc. Écrire le code Python de cette méthode cidessous.
defajouter_bloc(self,liste_transactions):# A compléter
Lorsqu’un utilisateur ajoute un nouveau bloc à la Blockchain, il l’envoie aux autres membres. Ainsi chaque utilisateur dispose sur sa propre machine d’une copie identique de la Blockchain. Donner le nom et la valeur de l’adresse IP à utiliser pour effectuer cet envoi.
On souhaite doter la classe Bloc d’une nouvelle méthode calculer_solde permettant de renvoyer le solde à l’issue de ce bloc. Recopier et compléter sur votre copie le code Python de cette méthode :
defcalculer_solde(self,utilisateur):ifself.precedentisNone:# cas de basesolde=0else:solde=...# appel récursif : calcul du solde au bloc précédentfortransactioninbloc.liste_transactionsif...==utilisateur:solde=solde-....elif...:...returnsolde
Écrire l’appel à la fonction calculer_solde permettant de calculer le solde
actuel de Alice
Partie B
Dans cette partie, on va améliorer la sécurité de la blockchain. Pour cela on enrichit la
classe Bloc comme indiqué ci-dessous:
classBloc:def__init__(self,liste_transactions,bloc_precedent):self.liste_transactions=liste_transactionsself.bloc_precedent=bloc_precedent# Définition de trois nouveaux attributsself.hash_bloc_precedent=self.donner_hash_precedent()self.nonce=0# Fixé arbitrairement et temporairement à 0 # avant le minage du blocself.hash=self.calculer_hash()# Définition de trois nouvelles méthodesdefdonner_hash_precedent(self):ifself.bloc_precedentisnotNone:returnself.bloc_precedent.hashelse:return"0"defcalculer_hash(self):"""calcule et renvoie le hash du bloc courant"""# Le code python n'est pas étudié dans cet exercicedefminage_bloc(self):"""modifie le nonce d'un bloc pour que son hash commence
par '00'"""# A compléter
La fonction calculer_hash produit une chaîne de caractères appelée hash qui
possède les propriétés suivantes :
Le hash d’un bloc dépend de toutes les données contenues dans le bloc et uniquement de ces données ;
Le calcul du hash d’un bloc est rapide et facile à calculer par une machine ;
La moindre modification dans le bloc produit un hash complètement différent ;
Il est impossible de déduire le bloc à partir de son hash.
Si deux blocs ont le même hash, c’est qu’ils sont parfaitement identiques.
L’attribut nonce est de type entier. Miner un bloc signifie trouver une valeur de
nonce de telle façon que l’attribut hash du bloc commence par les deux
caractères “00”. Compte tenu des propriétés précédentes, la seule façon de
trouver cette valeur est de procéder à une recherche exhaustive. Expliquer en
quoi consiste le fait de trouver une valeur par recherche exhaustive.
Dans la suite de l’exercice, on considère que tous les utilisateurs cherchent à miner le
nouveau bloc. Le premier qui réussit, l’ajoute à la blockchain et gagne une récompense
en nsicoin.
En justifiant votre réponse, donner la valeur de l’attribut hash_bloc_precedent
du bloc0.
Sachant que le hash est écrit sur 256 bits, donner le calcul permettant d’obtenir
le nombre de hash possibles.
Recopier et compléter sur votre copie le code python de la méthode
minage_bloc.
defminage_bloc(self):"""modifie le nonce d'un bloc pour que son hash commence par
'00' en énumérant tous les entiers naturels en partant de 0."""self.nonce=0self.hash=self.calculer_hash()while...:self.nonce=...self.hash=...
POO
Bac 2022 Metropole1/ Exercice 5
Cet exercice porte sur la Programmation Orientée Objet.
poo
Les participants à un jeu de LaserGame sont répartis en équipes et s’affrontent dans ce jeu de tir, revêtus d’une veste à capteurs et munis d’une arme factice émettant des infrarouges.
Les ordinateurs embarqués dans ces vestes utilisent la programmation orientée objet pour modéliser les joueurs. La classe Joueur est définie comme suit :
classJoueur:def__init__(self,pseudo,identifiant,equipe):"""constructeur """self.pseudo=pseudoself.equipe=equipeself.id=identifiantself.nb_de_tirs_emis=0self.liste_id_tirs_recus=[]self.est_actif=Truedeftire(self):"""méthode déclenchée par l'appui sur la gachette"""ifself.est_actif==True:self.nb_de_tirs_emis=self.nb_de_tirs_emis+1defest_determine(self):"""methode qui renvoie True si le joueur réalise un
grand nombre de tirs"""returnself.nb_de_tirs_emis>500defsubit_un_tir(self,id_recu):"""méthode déclenchée par les capteurs de la
veste"""ifself.est_actif==True:self.est_actif=Falseself.liste_id_tirs_recus.append(id_recu)
Question 1
Parmi les instructions suivantes, recopier celle qui permet de déclarer un objet joueur1, instance de la classe Joueur, correspondant à un joueur dont le pseudo est “Sniper”, dont l’identifiant est 319 et qui est intégré à l’équipe “A”:
Instruction 1 : joueur1 = ["Sniper", 319, "A"]
Instruction 2 : joueur1 = new Joueur["Sniper", 319, "A"]
La méthode subit_un_tir réalise les actions suivantes :
Lorsqu’un joueur actif subit un tir capté par sa veste, l’identifiant du tireur est ajouté à l’attribut liste_id_tirs_recus et l’attribut est_actifprend la valeur False (le joueur est désactivé). Il doit alors revenir à son camp de base pour être de nouveau actif.
A. Écrire la méthode redevenir_actifqui rend à nouveau le joueur actif
uniquement s’il était précédemment désactivé.
B. Écrire la méthode nb_de_tirs_recusqui renvoie le nombre de tirs reçus
par un joueur en utilisant son attribut liste_id_tirs_recus.
Question 3
Lorsque la partie est terminée, les participants rejoignent leur camp de base
respectif où un ordinateur, qui utilise la classe Base, récupère les données.
La classe Base est définie par :
ses attributs :
equipe : nom de l’équipe (str). Par exemple, “A” ,
liste_des_id_de_l_equipe qui correspond à la liste (list) des
identifiants connus des joueurs de l’équipe,
score : score (int) de l’équipe, dont la valeur initiale est 1000 ;
ses méthodes :
est_un_id_allie qui renvoie True si l’identifiant passé en paramètre
est un identifiant d’un joueur de l’équipe, False sinon,
incremente_score qui fait varier l’attribut score du nombre passé en
paramètre,
collecte_information qui récupère les statistiques d’un participant
passé en paramètre (instance de la classe Joueur) pour calculer le score
de l’équipe.
defcollecte_information(self,participant):ifparticipant.equipe==self.equipe:# test 1foridinparticipant.liste_id_tirs_recus:ifself.est_un_id_allie(id):# test 2self.incremente_score(-20)else:self.incremente_score(-10)
A. Indiquer le numéro du test (test 1 ou test 2) qui permet de vérifier qu’en fin de partie un participant égaré n’a pas rejoint par erreur la base adverse.
B. Décrire comment varie quantitativement le score de la base lorsqu’un joueur
de cette équipe a été touché par le tir d’un coéquipier.
On souhaite accorder à la base un bonus de 40 points pour chaque joueur
particulièrement déterminé (qui réalise un grand nombre de tirs).
Question 4:
Recopier et compléter, en utilisant les méthodes des classes Joueur et Base, les 2 lignes de codes suivantes qu’il faut ajouter à la fin de la méthode
collecte_information :
........#si le participant réalise un grand nombre de tirs.........#le score de la Base augmente de 40
Cet exercice porte sur les graphes, les algorithmes sur les graphes, les bases de données et les requêtes SQL.
graphesparcoursrécursivité
La société CarteMap développe une application de cartographie-GPS qui permettra aux automobilistes de définir un itinéraire et d’être guidés sur cet itinéraire. Dans le cadre du développement d’un prototype, la société CarteMap décide d’utiliser une carte fictive simplifiée comportant uniquement 7 villes : A, B, C, D, E, F et G et 9 routes (toutes les routes sont considérées à double sens).
Voici une description de cette carte :
A est relié à B par une route de 4 km de long ;
A est relié à E par une route de 4 km de long ;
B est relié à F par une route de 7 km de long ;
B est relié à G par une route de 5 km de long ;
C est relié à E par une route de 8 km de long ;
C est relié à D par une route de 4 km de long ;
D est relié à E par une route de 6 km de long ;
D est relié à F par une route de 8 km de long ;
F est relié à G par une route de 3 km de long.
Représenter ces villes et ces routes sur sa copie en utilisant un graphe pondéré, nommé G1.
Déterminer le chemin le plus court possible entre les villes A et D.
Définir la matrice d’adjacence du graphe G1 (en prenant les sommets dans l’ordre alphabétique).
Dans la suite de l’exercice, on ne tiendra plus compte de la distance entre les différentes villes et le graphe, non pondéré et représenté ci-dessous, sera utilisé :
Graphe G2
Chaque sommet est une ville, chaque arête est une route qui relie deux villes.
Proposer une implémentation en Python du graphe G2 à l’aide d’un dictionnaire.
Proposer un parcours en largeur du graphe G2 en partant de A.
La société CarteMap décide d’implémenter la recherche des itinéraires permettant de traverser le moins de villes possible. Par exemple, dans le cas du graphe G2, pour aller de A à E, l’itinéraire A-C-E permet de traverser une seule ville (la ville C), alors que l’itinéraire A-H-G-E oblige l’automobiliste à traverser 2 villes (H et G).
Le programme Python suivant a donc été développé (programme p1) :
tab_itineraires=[]defcherche_itineraires(G,start,end,chaine=[]):chaine=chaine+[start]ifstart==end:returnchaineforuinG[start]:ifunotinchaine:nchemin=cherche_itineraires(G,u,end,chaine)iflen(nchemin)!=0:tab_itineraires.append(nchemin)return[]defitineraires_court(G,dep,arr):cherche_itineraires(G,dep,arr)tab_court=...mini=float('inf')# mini prend la valeur + infiniforvintab_itineraires:iflen(v)<=...:mini=...forvintab_itineraires:iflen(v)==mini:tab_court.append(...)returntab_court
La fonction itineraires_court prend en paramètre un graphe G, un sommet de départ depet un sommet d’arrivéearr. Cette fonction renvoie une liste Python contenant tous les itinéraires pour aller de depàarr` en passant par le moins de villes possible.
la méthode append ajoute un élément à une liste Python ; par exemple,
tab.append(el) permet d’ajouter l’élément el à la liste Python tab ;
en python, l’expression ['a'] + ['b'] vaut ['a', 'b'];
en python float('inf') correspond à l’infini.
Expliquer pourquoi la fonction cherche_itineraires peut être qualifiée de fonction récursive.
Expliquer le rôle de la fonction cherche_itineraires dans le programme p1.
Compléter la fonction itineraires_court.
Les ingénieurs sont confrontés à un problème lors du test du programme p1. Voici les résultats obtenus en testant dans la console la fonction itineraires_court deux fois de suite (sans exécuter le programme entre les deux appels à la fonction itineraires_court) :
alors que dans le cas où le programme p1 est de nouveau exécuté entre les 2 appels à la fonction itineraires_court, on obtient des résultats corrects :
Arbres, parcours BFS (extrait 2024 centres etrangers J2, Ex 3)
arbreparcours
Partie B
On considère l’arborescence de fichiers de la figure suivante:
arborescence fichiers
on propose
l’implémentation suivante. L’attribut fils est une variable de type list contenant tous
les dossiers fils. Cette liste est vide dans le cas où le dossier est vide.
classDossier:def__init__(self,nom,liste):self.nom=nomself.fils=liste# liste d'objets de la classe Dossier
Écrire le code Python d’une méthode est_vide qui renvoie True lorsque le
dossier est vide et False sinon.
Écrire le code Python permettant d’instancier une variable var_multimedia de
la classe Dossier représentant le dossier multimedia de la figure précédente. Attention :
cela nécessite d’instancier tous les nœuds du sous-arbre de racine multimedia.
Recopier et compléter sur votre copie le code Python de la méthode parcours
suivante qui affiche les noms de tous les descendants d’un dossier en utilisant l’ordre préfixe.
defparcours(self):print(...)forfin...:...
Justifier que cette méthode parcours termine toujours sur une arborescence
de fichiers.
Proposer une modification de la méthode parcours pour que celle-ci effectue
plutôt un parcours suffixe (ou postfixe).
Expliquer la différence de comportement entre un appel à la méthode parcours
de la classe Dossier et une exécution de la commande UNIX ls
On considère la variable var_videos de type Dossier représentant le dossier
videos de la figure précédente. On souhaite que le code Python
var_videos.mkdir("documentaires") crée un dossier documentaires vide
dans le dossier var_videos.
Écrire le code Python de la méthode mkdir.
Écrire en Python une méthode contient(self, nom_dossier) qui renvoie
True si l’arborescence de racine self contient au moins un dossier de nom
nom_dossier et False sinon.
Avec l’implémentation de la classe Dossier de cette partie, expliquer comment
il serait possible de déterminer le dossier parent d’un dossier donné dans une
arborescence donnée. On attend ici l’idée principale de l’algorithme décrite en
français. On ne demande pas d’implémenter cet algorithme en Python.
Proposer une modification dans la méthode __init__ de la classe Dossier qui
permettrait de répondre à la question précédente beaucoup plus efficacement
et expliquer votre choix.
Exercice 1 25-NSIJ2ME1:
Cet exercice porte sur les arbres binaires et la programmation Python.
Le codage de Shannon-Fano est un système de codage utilisé pour la compression
sans pertes de données. Il a été mis au point par Robert Fano d’après une idée de
Claude Shannon.
Partie A
Dans cette partie, on va étudier l’utilisation des arbres de codage.
Un arbre de codage est un arbre binaire où chaque feuille contient un symbole du texte que l’on souhaite coder. Le code binaire d’un symbole s’obtient alors en concaténant les 0 et les 1 sur les branches qui mènent de la racine à la feuille contenant ce symbole.
Par exemple, pour l’arbre de codage donné en Figure 1, le symbole c est codé par le
mot binaire 1101, tandis que d est codé par le mot binaire 11000. Les codes binaires des symboles ne sont donc pas tous de la même taille. Pour décoder un mot binaire, il suffit de descendre dans l’arbre, depuis la racine, selon les 0 et les 1 qu’on lit jusqu’à trouver une feuille (et donc un symbole), puis de recommencer avec la suite du mot binaire pour décoder les symboles suivants.
Exemple d’arbre de codage
Écrire le mot binaire qui sera utilisé pour encoder le caractère espace,
représenté par le symbole
dans l’arbre.
Déterminer le texte codé par le mot binaire 0001110101111110011001.
Citer le type de parcours de l’arbre qui permettrait d’obtenir les symboles
classés par taille d’encodage croissante.
Partie B
Dans cette partie, on va utiliser le codage de Shannon-Fano pour encoder le texte :
je pense, donc je suis
Dans la méthode de Shannon-Fano, l’arbre de codage est calculé pour un texte donné
par l’algorithme suivant.
Étape 1 : classer les symboles du texte par nombre d’occurrences croissant;
Étape 2 : en gardant le classement obtenu, séparer les symboles en deux sous-
groupes de sorte que les totaux des nombres d’occurrences soient les plus
proches possibles dans les deux sous-groupes;
Étape 3 : placer tous les symboles du premier groupe dans le fils gauche (côté
étiqueté par 1), et ceux du second groupe dans le fils droit (côté étiqueté par 0);
Étape 4 : recommencer récursivement pour chacun des sous-groupes jusqu’à
ce qu’ils n’aient plus qu’un seul symbole ; on a alors une feuille étiquetée par ce
symbole.
Après avoir classé les symboles par nombre d’occurrences croissant (étape 1), on
obtient le tableau suivant :
symbole
i
u
c
o
d
,
p
n
j
s
e
_
nombre d’occurrences
1
1
1
1
1
1
1
2
2
3
4
4
Justifier par le calcul que l’étape 2 mène à la situation illustrée par la Figure 2.
Le résultat de l’étape 2
En appliquant l’algorithme de Shannon-Fano, on peut obtenir l’arbre de la Figure 3.
Arbre de codage obtenu par l’algorithme de Shannon-Fano
On rappelle qu’un arbre réduit à un seul nœud, c’est-à-dire réduit à une feuille, est de hauteur 0.
Donner la hauteur de l’arbre de la Figure 3 et préciser dans le contexte de
l’exercice ce qu’elle représente.
On rappelle que dans le code ASCII, chaque symbole est codé sur un octet.
Justifier, en comparant le codage ASCII et le codage de Shannon-Fano, que ce
second codage permet d’utiliser environ deux fois moins d’octets pour le texte :
je pense, donc je suis
Dessiner, en vous inspirant de l’arbre de la Figure 1, un arbre de codage qui
permettrait d’encoder le mot « chiffrer » en utilisant l’algorithme de Shannon-Fano.
Partie C
Dans cette partie, on souhaite écrire une fonction Python qui donnera le mot binaire
obtenu pour coder un texte avec l’algorithme de Shannon-Fano. On commence par la
fonction creer_dico_occ :
defcreer_dico_occ(texte):"""renvoie un dictionnaire dont les clés sont les
symboles de texte et les valeurs associées leur
nombre d'occurences dans texte"""dico={}forsymboleintexte:ifsymboleindico:dico[symbole]=...else:dico[symbole]=...returndico
Recopier et compléter les lignes 8 et 10 du code de la fonction
creer_dico_occ.
On dispose d’une fonction creer_tab_trie qui prend en paramètre un dictionnaire
construit avec la fonction creer_dico_occ et qui renvoie une liste de tuples classés dans l’ordre croissant d’occurrences des symboles.
Par exemple :
>>>texte='je pense, donc je suis'>>>dico=creer_dico_occ(texte)>>>creer_tab_trie(dico)[('i',1),('u',1),('c',1),('o',1),('d',1),(',',1),('p',1),('n',2),('j',2),('s',3),(' ',4),('e',4)]
Écrire une fonction somme_occ qui prend en paramètres un tableau tab de
tuples (symbole, nb_occ) et qui renvoie la somme des nombres
d’occurrences des symboles du tableau. Les tuples utilisés sont de même
structure que l’élément renvoyé dans l’exemple précédent.
On suppose pour la suite qu’on dispose d’une fonction separe qui sépare un tableau
trié en deux sous-tableaux de manière à ce que les sommes de ces derniers soient les
plus proches possible :
Recopier et compléter les lignes 9 et 11 du code de la fonction récursive
shannon qui prend en paramètres un caractère symbole et un tableau trié tab
et qui renvoie l’écriture binaire associée à symbole dans le tableau tab.
defshannon(symbole,tab):"""renvoie l'écriture binaire associée à symbole
dans le tableau trié tab"""iflen(tab)==1:return""else:t1,t2=separe(tab)ifsymbolein[elt[0]foreltint1]:return"1"+...else:return"0"+...
Décrire ce qui garantit la terminaison de la fonction récursive shannon.
Écrire une fonction encode_shannon qui prend en paramètre un texte de type
str et renvoie un mot binaire de type str obtenu après encodage par
l’algorithme de Shannon-Fano.
On pourra utiliser les fonctions vues précédemment qui sont recensées ci-
après.
creer_dico_occ(texte)
renvoie un dictionnaire dont les clés sont les symboles
du texte et les valeurs associées leur nombre
d'occurrences
creer_tab_trie(dico)
renvoie la liste crée à partir d'un dictionnaire
de couples (symbole, nb_occ)
separe(tab)
renvoie le tuple composé des 2 sous-tableaux triés
avec des sommes d'occurences proches
shannon(symbole, tab)
renvoie l'écriture binaire associée au symbole dans le
tableau trié tab
epreuve pratique
Exercices classiques pour se préparer à l'epreuve.
Écrire la fonction maximum_tableau, prenant en paramètre un tableau non vide de nombres tab (de type
list) et renvoyant le plus grand élément de ce tableau.
Programmer la fonction recherche, prenant en paramètres un tableau non vide tab (type list) d’entiers et un entier n, et qui renvoie l’indice de la dernière occurrence de l’élément cherché. Si l’élément n’est pas présent, la fonction renvoie None.
Écrire une fonction verifie qui prend en paramètre un tableau de valeurs numériques et qui renvoie True si ce tableau est trié dans l’ordre croissant, False sinon.
Le codage par différence (delta encoding en anglais) permet de compresser un tableau
d’entiers dont les valeurs sont proches les unes des autres. Le principe est de stocker la
première donnée en indiquant pour chaque autre donnée sa différence avec la précédente
plutôt que la donnée elle-même.
On se retrouve alors avec un tableau de données plus petit, nécessitant
moins de place en mémoire. Cette méthode se révèle efficace lorsque les valeurs consécutives
sont proches.
Programmer la fonction delta(liste) qui prend en paramètre un tableau non vide de nombres entiers
et qui renvoie un tableau contenant les valeurs entières compressées à l’aide cette technique.
Dans cet exercice, on considère des phrases composées de mots.
On appelle « mot » une chaîne de caractères composée avec des caractères choisis
parmi les 26 lettres minuscules ou majuscules de l’alphabet,
On appelle phrase une chaîne de caractères :
composée avec un ou plusieurs mots séparés entre eux par un seul
caractère espace ' ',
se finissant :
soit par un point '.' qui est alors collé au dernier mot,
soit par un point d’exclamation '!' ou d’interrogation '?' qui est alors
séparé du dernier mot par un seul caractère espace ' '.
Voici deux exemples de phrases :
‘Cet exercice est simple.’
‘Le point d exclamation est separe !’
Après avoir remarqué le lien entre le nombre de mots et le nombres de caractères espace
dans une phrase, programmer une fonction nombre_de_mots qui prend en paramètre une
phrase et renvoie le nombre de mots présents dans cette phrase.
>>>nombre_de_mots('Cet exercice est simple.')4>>>nombre_de_mots('Le point d exclamation est séparé !')6>>>nombre_de_mots('Combien de mots y a t il dans cette phrase ?')10>>>nombre_de_mots('Fin.')1
Dictionnaire. Fusion
Écrire une fonction ajoute_dictionnaires qui prend en paramètres deux
dictionnaires d1 et d2 dont les clés sont des nombres et renvoie le dictionnaire d défini de
la façon suivante :
Les clés de d sont celles de d1 et celles de d2 réunies.
Si une clé est présente dans les deux dictionnaires d1 et d2, sa valeur associée
dans le dictionnaire d est la somme de ses valeurs dans les dictionnaires d1 et d2.
Si une clé n’est présente que dans un des deux dictionnaires, sa valeur associée
dans le dictionnaire d est la même que sa valeur dans le dictionnaire où elle est
présente.
Utiliser scikit-learn pour predire la classe des exoplanètes: Lien
Courbes de transit
Etape 1: Courbe de transit
Outil de navigation: explorateur Python
On souhaite créer un outil de navigation qui permettra de se deplacer dans l’arborescence des dossiers et fichiers. Cela permettra de selectionner le-s fichier-s à traiter depuis la console python, sans modifier le code du programme.
Exemple:
On pourra au choix:
Utiliser, ou s’inspirer du fichier source suivant: astep_2025_v0.py
Programmer cette partie du programme de manière itérative (avec boucle while)
Programmer cette partie à l’aide d’un algorithme récursif (niveau Term NSI)
Les fonctions python qui permettent de naviguer entre dossiers et fichiers font partie du module os.path, dont la documentation officielle est ici: doc python
On utilisera principalement:
os.getcwd(): str, le dossier courant
os.path.abspath(): retourne le chemin absolu du dossier courant
os.chdir(d): change de dossier pour aller au dossier d
os.chdir('..'): remonte d’un niveau
os.listdir() ou os.listdir(d) : retourne la liste des fichiers et dossiers du dossier courant ou bien du dossier d
os.path.isdir(f): booléen True si f est un dossier
os.path.isfile(f): True si f est un fichier
f.endswith('.csv'): True si l’extension de f est .csv
Ouvrir et executer le fichier avec un IDE python quelconque. Pour le tracé de graphiques, il est recommandé d’utiliser IDLE (Python GUI) de la distribution Winpython.
Ouverture du fichier csv
Pour chacun des fichiers de données, ouvrir une nouvelle cellule du notebook et adapter le script suivant:
Les données utiles occupent les colonnes 0 (BJD) et 1 (FLUX) de la table. Les valeurs de FLUX (nuage de points en gris) étant très bruitées, il conviendra de réaliser un lissage des points (courbe rouge):
Le programme suivant réalise une moyenne glissante (courbe rouge): pour chaque indice i, on fait une moyenne du FLUX sur une fenêtre de 100 points, centrés sur l’indice i. y[i-50:i+50]
Compléter la fonction lissage, ainsi que le script aux points (1), (2), (3):
importmatplotlib.pyplotaspltfrommatplotlib.widgetsimportCursordefmoyenne(signal):"""fonction qui calcule la moyenne
sur les donnees de la liste signal
"""s=0# à completerreturns/bdeflissage(L,largeur):signal_filtre=L.copy()foriinrange(largeur//2,len(L)-largeur//2):signal=L[...:...]# on fait un slice# signal est le petit tableau de dimension egale à largeur# dont on fait la moyenne glissante# puis on place cette valeur moyenne dans signal_filtre, au rang isignal_filtre[i]=moyenne(...)returnsignal_filtrex=[]# colonne 0 de la table = BJDy=[]# colonne 1 de la table = FLUX# (1) import des valeurs de x et y à partir du fichier en ouverture# (2) utilisation des fonction lissageplt.clf()axes=plt.gca()plt.scatter(x,y,color='silver',marker='.',label='luminosité')plt.grid(True,which='both')plt.legend(loc='best')plt.title('luminosité transit')# (3) tracé de la courbe de lissageplt.plot(...,...,color='red',label='moyenne glissante')plt.grid(True,which='both')plt.legend(loc='best')cursor=Cursor(axes,useblit=True,color='red',linewidth=2)plt.show()
On peut alors utiliser les fonctions de la fenêtre graphique pour relever les coordonnées à la main des intersections des courbes:
option 1: le transit démarre au point A et termine au point B
option 2: le transit démarre au milieu du segment n°2 et termine au milieu du segment n°4
Avec l’option 2:
planète
tau (h)
incertitude sur tau
delta
incertitude sur delta
TOI 270-1
7.2
à definir
1-0.991
à definir
Suite
Lien vers l’etape 2: Notebook python utilisé comme calculatrice.
Traitement de données d’observation en astrophysique
Importer les données et librairies utiles
Dans une cellule d’un notebook, copier-coller les lignes suivantes:
importnumpyasnpimportpandasaspd# Constantes solaires Rsol=6.9598e8# rayon solaire en mrhosol=1408# densite solaire kg/m3Msol=1.98855e30# masses solaire en kg# Mercure, Jupiter (SI)V_merc=47# km/sR_Jup=71e6# m# Constantes terrestresMEarth=5.9736e24# masses de la terre en kgREarth=6.371e6# rayon de la terre en mrhoEarth=5514.# densité de la terre kg/m3# Changements d'unitéonemasinrad=np.pi/180./3600000.# 1 mas in radian kparsec=3.08567758e19# 1 kpc en mparsec=3.08567758e16# 1 pc en m# Constantes physiquesG=6.67e-11# m3 kg−1 s−2UA=149597870700# m
Planète TOI 270-01
Utilisez le notebook pour placer les valeurs de delta et tau mesurées sur la courbe de transit
Pour la planète TOI 270-01 du système TOI 270, (valeurs à vérifier sur la courbe de transit):
# Données de l'etoile R_star=Rsol*0.37M_star=Msol*0.36# Observables sur la courbe de transitdelta=0.0044# sans unitétau=4600# s
Rayon planete a partir de delta
$$R_p = R_{star}\times \sqrt{delta}$$
La racine carrée est une fonction de la librairie numpy, avec numpy.sqrt
Le résultat du calcul peut nécessiter l’écriture d’un format particulier pour faciliter la lecture:
Utilisez le notebook pour calculer le rayon de la planète observée:
## Calcul du rayon planétaire Rp=np.sqrt(delta)*R_starprint("Rp = {:.3e} m.".format(Rp))print("Rp = {:5.3f} REarth.".format(Rp/REarth))# ---- affichage console --- #Rp=1.708e+07m.Rp=2.681REarth.
Faire ces mêmes calculs pour chaque planète observable.
Synthèse des résultats: fichier csv
Les fichiers csv sont interopérables: on peut les editer avec un editeur de texte, ou un tableur. On peut les importer facilement pour un traitement en langage python.
Utiliser un tableur
Les courbes de transit ont permis de mesurer les valeurs de profondeur de transit $\delta$ et de durée de transit $\tau$.
Ces valeurs seront reportées dans un fichier csv avec les autres informations sur les planètes et leur étoile. Utiliser un tableur. Attention à bien utiliser des points comme séparateur décimal.
tableau rempli à l'aide d'un tableur
Exporter (ou enregistrer) en format csv.
On peut vérifier en ouvrant le fichier csv que les données sont mises dans un format particulier (séparation à l’aide d’un point virgule…)
fichier csv
Import dans le notebook python
L’import avec la librairie pandas se fait de la manière suivante: (rien de plus simple)
df=pd.read_csv('exoplanetes.csv',sep=';')df
Suite
La suite (étape 3) va demander un apprentissage d’une nouvelle structure de données: le dataframe. Cela représente plusieurs avantages:
la visualisation des données en table dans un notebook python,
la manipulation des données (creation de nouvelles colonnes calculées, projection, selection, …) qui est similaire au travail déjà vu sur les tables (SQL). Le langage diffère, mais l’esprit est le même.
L’utilisation des librairies de traitement de données est facilitée (seaborn, …)
La programmation du jeu de Dominos a été réalisée dans cette séance. (sans interface graphique)
Vous allez réaliser un jeu de Dominos avec l’interface Tkinter. A partir d’un fichier existant, vous allez ajouter des fonctionnalités utiles. Vous devrez collaborer efficacement et vous partager le travail équitablement.
de rendre un programme fonctionnel, sur la base de celui fourni au départ. Le code du programme peut être divisé en 2 fichiers, si besoin.
le code du programme devra être correctement commenté et lisible.
Sur votre cahier de laboratoire: vous expliquerez quel a été votre rôle personnel dans la séance: Les choix que vous avez fait, les explications que vous voulez ajouter.
Il se peut que l’editeur Spyder présente des problèmes avec la librairie TKinter. Le fichier dominos_projet.py peut ne pas s’executer. Choisir alors un autre editeur.
Travail à réaliser
Dans la classe Partie
étape 1
classPartie:(...)defajouter_fin(self,D):"""
ajoute l'objet domino D à la fin de la chaine:
ajoute d'abord D à self.end.suiv
puis D à self.end
:param D: instance de Domino
"""defRAZ(self):"""
Détache le premier élement du reste de la chaine:
met d'abord self.first.suiv à None
puis self.end prend la valeur de self.first
"""defpose_correcte(self,val):"""
teste si le nouveau domino à poser est compatible avec le dernier de la chaine
comparer alors val (équivaut à val1 0..6) du domino à poser avec val2 du dernier
domino de la partie
:param val: int
:return: bool, True si les valeurs sont identiques
"""
Compléter les fonctions ajouter_fin, et RAZà partir des informations contenues dans le script.
étape 2
Dans la classe Partie: Compléter la méthode de classe pose_correcte: celle-ci devra renvoyer True si le domino posé respecte la règle du jeu, à savoir que les nombres adjacents des 2 dominos sont identiques. Sinon, la fonction retourne False.
étape 3: testez vos fonctions de la classe Partie
Dans le programme principal if __name__ == '__main__'::
Après la déclaration app = Game(partie1), ajouter les lignes suivantes:
# ajoutsD2=Domino(4,3)print(partie1.pose_correcte(4))# verifie si la pose 2:4 => 4:3 est OKpartie1.ajouter_fin(D2)# ajoute le nouveau Domino D2print(partie1)# affiche le jeu dans la consoleapp.dessine()# dessine le jeu dans la fenêtre TKinter
Si tout se passe bien, vous devriez obtenir:
True
2:4 => 4:3
Dans la classe Game
étape 1
Comprendre comment on joue
classGame(Tk):(...)defreadtext(self):"""
fonction appelée lorsque l'on valide avec le bouton VALIDER
- lecture du contenu de la textBox avec le format de données
2,4,[E O S N]
soit valeur1,valeur2,direction
alors valeur1 -> self.val1 et valeur2 -> self.val2
direction -> self.dir
- ou bien
2,4
soit valeur1,valeur2
alors seuls les attributs self.val1 et self.val2 sont modifés
self.dir n'est pas modifiée (E au debut)
exemples:
---------
- la textBox est validée avec: 4,2,S
alors s vaut [4,2,S\n] et on ajoute le domino 4,2 à la partie
dans la direction S (Sud)
- la textBox est validée avec: 4,2
alors s vaut [4,2] et on ajoute le domino 4,2 à la partie sans
changer de direction
"""# lecture de la textBoxresult=self.textBox.get("1.0","end")# decoupage de la chaine de caracteres selon les virguless=str(result).split(',')# AJOUTER condition avec self.partie.pose_correcte(s[1])# tout le reste est declenché par condition == True# sinon: message d'erreur sur text_affichage qui demande de corrigerself.text_affichage.set('DOMINO joué\n{},{}'.format(s[0],s[1]))self.partie.ajouter_fin(# a completer (1)print(self.partie)iflen(s)>2:self.dir=# à completer (2)self.dessine()
Au repère à completer (1):
Completer la fonction ajouter_fin avec pour paramètre le nouveau Domino à poser.
Il faut créer un nouvelle instance de Domino avec pour attributs int(s[0]) et int(s[1]), ce qui signifie Domino(int(s[0]),int(s[1]))
Au repère à completer (2):
self.dir prend la valeur de str(s[2][0]), c’est à dire le premier caractère de s[2].
étape 2
Modifier la méthode de classe readtextde la classe Game pour tenir compte de la méthode pose_correcte de Partie: si la pose est correcte, et que la méthode self.partie.pose_correcte() retourne True, alors poser le domino sur la table de jeu. Sinon, demander de jouer un autre domino.
Suite du projet
La suite dependra de l’objectif visé.
Le jeu de Dominos se joue avec un ensemble de 28 dominos:
Le jeu peut démarrer avec un certain nombre de dominos affectés au joueur, ainsi qu’une pioche avec les dominos restants.
Une extension du jeu pourrait permettre à 2 joueurs de jouer à tour de rôle. Cette extension du projet est plus complexe, car elle demande de programmer les objets de la fenêtre TKinter.
Pygame Snake
Jeu du Snake avec le module Pygame
Pygame est une librairie Python apportant la SDL (Simple Directmedia Library), une bibliothèque libre multi-plateformes permettant la gestion du multimédia dans la programmation. Utile pour la programmation de jeux avec graphiques
Ce projet consiste à realiser (en partie) le jeu Snake. Il traite des types abstraits personnalisés.
Le Snake est un genre de jeu vidéo dans lequel le joueur dirige un serpent qui grandit et constitue ainsi lui-même un obstacle. Ce jeu est apparu pour la première fois en 1976 (Editeur Gremlin) sous le nom de Blockade. Les consoles de jeu à l’époque possédaient un CPU de 8-bit (MOS Technology 6507 @ 1.19 MHz) et une RAM de 128 octets. Depuis, le jeu a connu de nombreux clones.
snake retro game
Le type serpent proposera pour interface les fonctions suivantes:
affiche
tete
ajoute_tete
supprime_queue
Une version de ce projet sur microbit est accessible ici.
Editeur
Le module Pygame est installé sur votre ordinateur. Utilisez un IDE python comme IDLE ou pyzo.
Script initial
Le script suivant donne les éléments de base du programme.
Copier-coller celui-ci dans la fenêtre du fichier main.py.
Creation d’un type abstrait serpent
Le serpent est un objet qui stocke les données d’une certaine manière, et qui propose quelques fonctions utiles pour interragir avec lui (une interface). Il s’agit donc d’un type abstrait.
Pour représenter le serpent, comme dans le jeu snake, les coordonnées des pixels du serpent seront stockées dans une Liste [(x1,y1),(x2,y2),...].
Interface
Vous allez programmer chaque fonction de l’interface à partir des renseignements suivants. Ces fonctions seront placées dans le proggramme, avant la boucle principale.
fonction affiche
defaffiche(S):# affiche tous les pixels du serpent# a partir de leurs coordonnees dans S# utilise une boucle for
L’affichage de chaque pixel du serpent necessite une boucle bornée:
deftete(S):# retourne les coordonnees x, y de la tete du serpent# qui sont stockees dans le dernier element S[-1]# sous la forme d'un tuple (x,y)
fonction ajoute_tete
Il peut être necessaire d’ajouter un pixel au serpent. Celui-ci s’ajoutera à la fin de la liste de coordonnées:
def ajoute_tete(S, x, y):
# ajoute un tupple (x,y) a la fin de la liste S
fonction supprime_queue
A chaque déplacement, cela ajoute un pixel à la fin de la liste. Il s’agit de la tête du serpent. Il faut alors retirer le premier pixel (serpent[0]) si l’on veut que sa longueur reste constante.
deplacement du serpent vers le bas
defsupprime_queue(S):# decale toutes les valeurs de la liste S vers la gauche:# a l'aide d'une boucle bornee sur les indices i:# copie toutes les valeurs S[i+1] dans S[i]# puis supprime le dernier element
Dans le programme main.py
Définissez une variable qui stocke les coordonnées du serpent: serpent = [(400,200),(400,210), (400,220), (400,230)]
Dans la boucle principale:
recuperer les coordonnées x1 et y1 de la tête du serpent (utiliser la fonction tete)
modifier les valeurs de x1 et y1 en fonction de la direction du deplacement
Ajoutez des conditions pour que le pixel ne sorte pas de l’écran. On peut faire changer de direction lorsque le bord de l’écran est touché par le pixel: if x1 > 800 or x1 < 0: ...
Ajouter les coordonnées du pixel x1, y1 à la fin de la liste serpent (ajoute_tete)
Supprimer le premier pixel du serpent, celui placé en serpent[0] avec supprime_queue
Afficher le serpent une fois ses coordonnées recalculées avec la fonction affiche.
Le jeu devrait être à present fonctionnel.
Créer un module
Vous pouvez maintenant améliorer la mise en forme de votre programme: Mettre les fonctions de l’interface dans un nouveau fichier.
Dans le fichier que vous nommerez utils.py, déplacer les fonctions: tete, ajoute_tete, et supprime_queue. (Sur Trinket, il suffira d’ajouter un nouvel onglet dans l’editeur python et de nommer cet onglet: utils.py).
Pour faire référence à ces fonctions, il faudra ajouter la ligne suivante dans le programme main.py:
from utils import *
Questions
Expliquer: Comment le programme gère les déplacements du serpent?
Cette gestion des déplacements, est-elle facilitée par l’interface du type serpent? Si oui, comment?
Quelles fonctionnalités du jeu manque-t-il pour que celui-ci soit complet?
Si vous deviez créer le jeu complet:
quelles fonctions ajouteriez vous à l’interface serpent?
Quelle autre structure de données envisageriez-vous?
Correction fichier main.py
importpygamefromutilsimport*pygame.init()white=(255,255,255)black=(0,0,0)red=(255,0,0)dis=pygame.display.set_mode((800,600))game_over=Falsex1=300y1=300x1_change=0y1_change=0clock=pygame.time.Clock()serpent=[(400,200),(400,210),(400,220),(400,230)]defaffiche(S):# affiche tous les pixels du serpent# a partir de leurs coordonnees dans SforcoordinS:x,y=coordpygame.draw.rect(dis,black,[x,y,10,10])whilenotgame_over:foreventinpygame.event.get():ifevent.type==pygame.QUIT:game_over=Trueifevent.type==pygame.KEYDOWN:ifevent.key==pygame.K_LEFT:x1_change=-10y1_change=0elifevent.key==pygame.K_RIGHT:x1_change=10y1_change=0elifevent.key==pygame.K_UP:y1_change=-10x1_change=0elifevent.key==pygame.K_DOWN:y1_change=10x1_change=0x1,y1=serpent[-1]x1+=x1_changey1+=y1_changeifx1>800orx1<0:x1_change=-x1_changeify1>600ory1<0:y1_change=-y1_changeajoute_tete(serpent,x1,y1)supprime_queue(serpent)dis.fill(white)affiche(serpent)pygame.display.update()clock.tick(30)pygame.quit()quit()
Correction fichier utlis.py
importpygamedeftete(S):# recupere les coordonnees x, y de la tete du serpentreturnS[-1][0],S[-1][1]defajoute_tete(S,x,y):# ajoute un tupple (x,y) a la fin de la liste SS.append((x,y))defsupprime_queue(S):# decale toutes les valeurs de la liste S vers la gauche:# copie toutes les valeurs S[i+1] dans S[i]# puis supprime le dernier elementforiinrange(len(S)-1):S[i]=S[i+1]S.pop()
Microbit: Petit jeu de type Snake en 2D
Se rendre à la page du TP de term NSI et approfondir la seance.
Le jeu du Morpion est un jeu de réflexion se pratiquant à deux joueurs au tour par tour et dont le but est de créer le premier un alignement sur une grille (3x3).
Vous allez programmer le jeu du Morpion contre l’ordinateur. L’ordinateur devra repondre à chacun des coups du joueur et, si possible, remporter la partie.
Pour traiter ce projet, il est fortement recommandé de bien maitriser l’exercice 3.1, vues dans le TD sur les tableaux.
Afin d’analyser la partie, et prevoir les prochains coups à jouer, l’ordinateur utilisera les fonctions suivantes, que vous devrez programmer:
compteur
victoire
cherche_car
Prévoir ensuite le prochain coup à partir des informations fournies, et créez un jeu, où l’ordinateur ne sera jamais perdant.
Compteur du nombre de caractères identiques
Lire et tester le programme suivant:
Exemple: Compte le nombre de X dans une ligne, colonne ou diagonale
# Vérifier si la ligne 0 contient trois symboles identiquesliste_X=[0,0,0]liste_Y=[0,1,2]compteur=0foriinrange(len(liste_X)):x=liste_X[i]y=liste_Y[i]ifmorpion[x][y]=='X':compteur+=1print("il y a ",compteur,"cases X dans la ligne 0")
Dans la boucle for, l’indice i varie de 0 à 2.
Pour i=0, x a pour valeur liste_X[0] -> 0 et y a pour valeur liste_Y[0] -> 0. Le couple x,y vaut alors 0,0.
On utilise ces coordonnées pour relever le symbole de la case morpion[0][0]. C’est un X. On augmente alors le compteur d’une unité (on compte les X).
On continue dans la boucle for avec les cases 0,1 puis 0,2.
Etape 1: Créer une fonction compteur qui prend une grille, un caractère car, une liste liste_X et une liste liste_Y en paramètres. Cette fonction devra retourner le nombre de fois que ce caractère car apparait.
Exemple: utiliser la fonction compteur
# Etape 1morpion=[['X','O','X'],['O','X',' '],[' ','O','O']]defcompteur(grille,car,liste_X,liste_Y):c=0foriinrange(len(liste_X)):# à completer x=...y=...ifgrille[][]...c=c+...returnccompteur(morpion,'X',[0,0,0],[0,1,2])# retourne:2
premiere étape de la boucle for
La fonction retourne 2: à la premiere ligne, il y a bien 2 caractères ‘X’.
Utilisez votre fonction
Etape 2: utilisez votre fonction pour déterminer le nombre de ‘X’ dans chacune des lignes, dans chacune des colonnes, et dans chacune des diagonales (8 appels de la fonction). Placer chaque valeur dans une liste L, puis afficher celle-ci.
# Etape 2L=[]L.append(compteur(morpion,'X',[0,0,0],[0,1,2]))L.append(compteur(......print(L)
Victoire
Etape 3: Créer une fonction victoire, qui prend une grille de morpion en paramètre, ainsi qu’un caractère car (qui vaut X ou O), et vérifie si la condition de victoire est réalisée pour le joueur X ou O. La fonction retournera un booléen True/False.
Exemple: Victoire des X
# Etape 3morpion=[['X','O','X'],['O','X',' '],[' ','O','X']]defvictoire(grille,car):b1=compteur(grille,car,[0,0,0],[0,1,2])b2=compteur(grille,car,[1,1,1],[0,1,2])# a completerb8=compteur(grille,...)returnb1==3or...victoire(morpion,'X')# retourne:Truevictoire(morpion,'O')# retourne:False
Detection case vide [niveau Term NSI]
Etape 4: Ecrire une fonction cherche_car(grille,car,liste_X,liste_Y) qui verifie si les cases de coordonnées (liste_X[0], liste_Y[0]), (liste_X[1], liste_Y[1]), (liste_X[2], liste_Y[2]) contiennent au moins un symbole car, et retourne les coordonnées de la première case contenant le caractère car.
Exemple: recherche d’un espace ’ ’ dans la ligne 2
# Etape 4morpion=[['X','O','X'],['O','X',' '],[' ','O','O']]defcherche_car(grille,car,liste_X,liste_Y):foriinrange(len(liste_X)):x=liste_X[..y=liste_Y[..ifgrille[..][..]==...:returnx,ycherche_car(morpion,' ',[2,2,2],[0,1,2])# retourne:(2,0)
La fonction retourne (2,0), car à la case de coordonnées [2][0], il y a un symbole ' '.
recherche d'un caractère espace ' ' dans la dernière ligne
Exemple: recherche du premier espace ’ ’ dans tout la grille
Lorsque l’on recherche un caractère dans TOUTE la grille, il y a 9 coordonnées à renseigner pour chacune des listes.
Stratégie de l’ordinateur [Niveau Term NSI]
Etape 5: créer une fonction jeu_de_defense, qui prend pour paramètre grille, et car_attaquant, qui vaudra ‘X’ ou ‘O’.
Cette fonction va permettre de programmer le jeu complet, pour jouer contre l’ordinateur.
Pour chacune des lignes, puis pour chacune des colonnes, et enfin chaque diagonale:
Si la ligne contient 2 caractères ‘X’ (fonction compteur, et que la ligne contient un espace (cherche_car ne retourne pas None), alors retourner les coordonnées x,y retournées par la fonction cherche_car.
Sinon, retourner None
defjeu_de_defense(grille,car_attaquant):ifcompteur(grille,car_attaquant,[0,0,0],[0,1,2])==2andcherche_car(grille,' ',[0,0,0],[0,1,2])!=None:# jouer dans une case vide de la ligne 0jouer_case=cherche_car(grille,' ',[0,0,0],[0,1,2])elifcompteur(grille,car_attaquant,[1,1,1],[0,1,2])==2andcherche_car(grille,' ',[1,1,1],[0,1,2])!=None:# jouer dans une case vide de la ligne 1jouer_case=cherche_car(grille,' ',[1,1,1],[0,1,2])elif(...)(...)elifcompteur(grille,car_attaquant,[0,1,2],[0,0,0])==2andcherche_car(grille,' ',[0,1,2],[0,0,0])!=None:# jouer dans une case vide de la colonne 0jouer_case=cherche_car(grille,' ',[0,1,2],[0,0,0])(...)else:jouer_case=Nonereturnjouer_case
Pour appeler la fonction, et bloquer l’adversaire ‘X’, faire:
Ainsi, si aucune des lignes, colonnes, diagonale ne correspond ne contient deux caratères ‘X’ alignés, retourner la premiers case vide trouvée dans la grille: ce sera l’emplacement où l’ordinateur ‘O’ peut jouer.
Pour élaborer une stratégie plus avancée de l’ordinateur, on pourra consulter la page dédiée: site tictactoe.com
site TICTACTOEFREE.COM
Une ouverture possible sur la suite du programme de terminale peut aussi vous amener à consulter l’algorithme du minimax: page wikipedia
Interface joueur
Pour cette deuxième phase du projet, vous pourrez télécharger le script python contenant toutes les fonctions nécéssaires: telecharger
Vous allez maintenant programmer l’interface du joueur, en lui demandant les coordonnées x,y où il placera son pion 'X'. La grille de morpion devra être modifiée en fonction de son choix, à condition que la case contienne bien ’ ‘.
# Etape 6Fin_de_partie=Falsewhilenotvictoire(morpion,'X')andnotvictoire(morpion,'O')andnotFin_de_partie:affiche(morpion)x=int(input("jouer à la ligne (0,1,2), 3=Fin :"))y=int(..)...
Pour jouer contre l’ORDINATEUR. (utiliser la fonction jeu_de_defense pour prevoir la case dans laquelle il devra jouer).
Organisez au mieux votre script. Commentez vos fonctions.
Prévoir et anticiper toutes les erreurs possibles de saisie du joueur, tous les defauts possibles qui peuvent survenir dans la partie (plus de O que de X, erreurs avec les coordonnées saisies, terminaison de la boucle while, …). On pourra ajouter des structures conditionnelles supplémentaires, ou bien des tests d’assertion, ou autres mécanismes. (try.. except, raise,…): Voir cours sur la mise au poin d’un programme: python avancé
Utiliser une structure de données Pile pour permettre un retour en arriere (le joueur efface ses coups précédents).
Projet 2: jeu du Sudoku [Term NSI]
Le jeu du Sudoku est une jeu de reflexion utilisant une grille (9x9).
Le but du jeu appelé Sudoku, est de remplir la grille avec une série de chiffres tous différents, qui ne se trouvent jamais plus d’une fois sur une même ligne, dans une même colonne ou dans une même région (également appelée « bloc », « groupe », « secteur » ou « sous-grille »).
Vous allez proposer une grille au joueur, partiellement remplie.
A chaque tour de jeu:
Demander au joueur les coordonnées de jeu dans la grille, ainsi que le chiffre à placer. Le joueur ne peut joueur que dans une case contenant déjà un zero, pas une autre valeur.
Si le joueur choisit un chiffre et un emplacement qui génèrent un doublon, alors informez du problème rencontré.
Demandez lui s’il valide son choix (on modifie alors la grille), ou s’il ne veut pas valider (on laisse le zero).
Vérifier si la grille est gagnante.
Demander au joueur s’il continue la partie, ou s’il veut revenir en arrière (on remet les zeros aux emplacements modifiés, en remontant selon une PILE).
On recommence avec un nouveau tour de jeu.
Vous allez programmer les fonctions qui vont vérifier, à chaque essai du joueur, si les chiffres placés (autres que 0) sont tous différents:
dans les différentes lignes: fonction check_lignes
dans les différentes colonnes: fonction check_col
et dans les différentes regions (blocs 3x3): check_blocs
Vous devrez aussi programmer une fonction qui verifie si la grille est entièrement, et correctement remplie: check_victoire
Le joueur aura la possibilité de revenir en arrière (un ou plusieurs coups), et poursuivre la partie.
exemple de grille et solution
Il est fortement recommandé d’utiliser les fonctions de l’exercice 3.2, vues à la page des exercices sur les tableaux.
Pour les élèves de Terminale:
Organisez au mieux votre script. Commentez vos fonctions.
Prévoir et anticiper toutes les erreurs possibles de saisie du joueur, tous les defauts possibles qui peuvent survenir dans la partie (plus de O que de X, erreurs avec les coordonnées saisies, terminaison de la boucle while, …). On pourra ajouter des structures conditionnelles supplémentaires, ou bien des tests d’assertion, ou autres mécanismes. (try.. except, raise,…): Voir cours sur la mise au poin d’un programme: python avancé
Utiliser une structure de données Pile pour permettre un retour en arriere (le joueur efface ses coups précédents).
La page suivante montre quelques possibilités de dessins réalisés avec le module turtle. Ces dessins sont plutôt dirigés vers la réalisation de fractales: l’idée est de reproduire un même motif à différentes échelles, pour obtenir une image d’ensemble. Le script utilisé peut être recursif.
Mais ce n’est pas le seul type de réalisation possible avec un algorithme.
Le dessin algorithmique va permettre:
de dessiner, répéter, ou de remplir la page avec une grande précision (pavages, angles droits, …)
de gérer les proportions dans l’image, dans le remplissage, la position des éléments dans la page
d’ajouter du désordre calculé dans le motif
…
Piet Mondrian/ Composition en rouge, jaune, bleu et noir / 1926
Les compositions de Piet Mondrian sont créées de façon à être parfaitement équilibrées, que chaque élément soit justifié et que ses toiles relèvent d’une harmonie parfaite entre les lignes et les couleurs
Piet Mondrian COMPOSITION EN COULEUR A, 1917
Vera Molnar
Suggestion de projet
La réalisation d’une ou plusieurs oeuvres artistiques à l’aide d’un algorithme devra s’accompagner d’un guide de lecture et compréhension de l’oeuvre. Montrer également quels sont les ingrédients de programmation choisis. Et discuter de l’efficacité de celui-ci, en rapport avec la complexité algorithmique.
Liens
Piet Mondrian wikipediaconsidéré comme l’un des fondateurs de l’art abstrait. Il peint des plans rectangulaires de dimensions variables, et aux couleurs dites pures.
Vera Molnar wikipediaen 1967, elle co-fonde le groupe Art et Informatique à l’Institut d’Esthétique et des Sciences de l’art de Paris. C’est dans ce cadre qu’elle réalisera ses premiers travaux sur un ordinateur.
« Son art, conduit de façon expérimentale, porte sur la forme, sa transformation, son déplacement, sa perception. Son travail s’accompagne d’une intense réflexion théorique sur les moyens de la création et les mécanismes de la vision. »
Presentation des artistes pour une sequence de cours en classe élémentaire le sens du desordre, ppt
ABR applications
ABR: sujet 1
Vous programmez un jeu narratif, ou le personnage peut collecter, gagner ou perdre des objets. Il possède ainsi un (très) grand sac à dos. Pour représenter ces objets, vous les numérotez (à l’aide d’une clé) d’une manière qui permettra de facilement les retrouver. Vous placerez ces clés dans un arbre binaire de recherche lorsque le personnage gagne l’objet. Et vous retirerez cette clé lorsqu’il perd l’objet.
Vous aurez besoin ainsi de 2 structures de données:
l’ABR pour ranger les clés
un tableau pour placer les couples clé,nom_de_l_objet
Pour organiser votre sac à dos, les clés possèderont un code commun (voir exercice de bac pages 7,8) lorsqu’il s’agit d’une même famille d’objets. Par exemple, le couteau et le glaive pourraient être codés de la manière suivante:
'01100001', 'couteau'
'01100010', 'glaive'
Les 4 premiers caractères de la clé, 0110 codent alors les armes de contact.
On peut imaginer d’autres rubriques, et d’autres codes, pour classer les différents objets.
Etape 1: Créer un programme qui place les très nombreux objets du sac à dos dans un ABR.
Etape 2: Programmez les fonctions qui permettent:
d’ajouter un nouvel objet
de retirer un objet du sac à dos
d’afficher la liste des objets du sac à dos, pour une famille d’objets donnée.
ABR: sujet 2
vue d'artiste de la bibliothèque de Babel
La célèbre bibliothèque infinie de Jorge Luis Borges issue de son récit La bibliothèque de Babel a été récemment modélisée par un certain Jamie Zawinski, d’après la description faite au début du récit.
Imaginez une bibliothèque contenant un extrêmement grand nombre de livres. Cette bibliothèque est organisée de la manière suivante :
Il y a des milliers de pièces différentes.
Chaque pièce est repérée par une suite de trois lettres, et dans cette pièce sont rangés tous les livres dont les titres commencent par ces trois lettres.
Chaque pièce possède deux sorties, une à droite et une à gauche.
La sortie de gauche mène soit à une salle dont les trois lettres sont situées avant dans l’ordre alphabétique, soit nulle part.
La sortie de droite mène soit à une salle dont les trois lettres sont situées après dans l’ordre alphabétique, soit nulle part.
Une représentation de cette bibliothèque peut être donnée sous la forme d’un arbre binaire tel que le suivant :
exemple de placement des données dans un ABR. Ordre alphabetique
Questions:
Combien de pieces différentes pourrait comporter cette bibliothèque, si celle-ci devait représenter toutes les combinaisons de clés de 3 lettres possible?
Où se placerait la salle de clé KRO?
Etape 1: Le projet pourrait consister à établir une liste de clés, dans un fichier. Chaque ligne sera constituée de la clé, ainsi que d’un mot dont les premières lettres débutent par cette clé. (une table de hashage). Il n’est pas necessaire d’être exhaustif, et d’envisager toutes les clés existantes.
Etape 2: Vous placerez ces clés dans un arbre binaire de recherche, avec pour information à chaque noeud le couple (clé,ligne_dans_la_table)
Etape 3: Programmez la fonction qui permet de trouver une clé dans l’ABR, puis de retrouver les informations correspondantes dans la table.
ABR: sujet 3
Programmer un index inversé pour les mots d’un roman.
Etape 1: Ouvrir les 10 premières pages du roman The Time Machine de H.G. Wells avec les outils python (fonction open). Utiliser un compteur de phrases et de mots. Chaque mot sera associé à une position dans le texte du type (numero_phrase, numero_mot_dans_la_phrase)
Etape 2: Placer alors tous les mots dans un ABR au fur et à mesure de leur apparition. La donnée stockée dans le noeud de l’arbre sera constituée d’une paire (clé,valeur), où la clé est le mot, la valeur est la position dans le texte pour sa première occurence.
Etape 3: Utiliser une table pour placer toutes les occurences de chaque mot. La donnée stockée dans chaque noeud servira maintenant à retrouver la position de cette information dans la table et sera constituée du couple: (mot,ligne_dans_la_table).
Mise au point d’un programme. Modules, tests, docstring: Lien
Liens
Le sujet 2 est inspiré de la page zonensi.fr, et également Numérique et Sciences Informatiques, 24 leçons avec exercices corrigés, Balabonski, Conchon, Filliâtre, Nguyen, Editions Ellipses
La durée de l’epreuve est de 20 minutes, partagés en:
10 min d’exposé oral.
10 min d’entretien
Construire sa question en rapport avec la spécialité NSI
L’élève doit proposer 2 questions au jury, qui choisira celle qui sera presentée par le candidat. Ces questions portent obligatoirement sur les 2 spécialités de terminale, en combinaison. (une spécialité par question, ou 2 specialités représentées sur l’une des 2 questions, et une ou deux spé pour la 2e question).
Grand Oral et enseignement de spécialité NSI (MEN)
Résumé:
L’énoncé de la question est le point final d’une réflexion qui fait l’objet d’un temps de maturation. Ce travail est progressif et s’affine avec l’avancée du programme et l’appropriation des notions.
Elle s’appuie sur des connaissances acquises lors de l’enseignement scolaire et permet de se projeter vers la poursuite des études dans l’enseignement supérieur.
Lors de l’entretien, le jury voudra vous faire developper des points de votre presentation orale. Il y aura alors un contrôle des connaissances evoquées, en lien avec la matière. Il peut aussi y avoir un échange sur le projet d’orientation du candidat, et sur la maturation de celui-ci. Cette construction personnelle rend authentique le propos. Il permet à l’élève d’y associer ses préoccupations personnelles et sociales, ses engagements, ses réflexions sur l’avenir, etc.
Voici une liste de thèmes dans lequel vous pourrez concevoir votre Question.
Le document propose 45 questions, partagées sur ces thèmes. Cette liste n’est bien sûr absolument pas limitative.
L’histoire de l’informatique
Langages et programmation
Données structurées et structures de données
Algorithmique
Bases de données
Architectures matérielles, systèmes d’exploitation et réseaux
Le document traite 3 questions. Vous comprendrez la méthodologie attendue pour en construire la réponse:
« Les ruches connectées vont-elle sauver les abeilles ? »
« Comment faire apprendre un robot ? »
« Comment partager des biens culturels ? »
Les sites des editeurs
Les éditeurs publient des pages sur l’épreuve, d’autres exemples de sujets, et des liens pour approfondir les thèmes.
Par exemple, le site LeLivreScolaire propose dans cette page des exemples de Questions combinant Mathématiques et NSI.
Ressources
Vous êtes dans une phase de construction du savoir, sur un enseignement qui est nouveau (pour vous). Il est important de commencer à explorer les articles de journaux plus généralistes qui vont assurer votre base de connaissances, et approfondir votre réflexion…
Voici les principales ressources pour explorer les articles sur les thèmes de l’informatique. Un recueil et résumé des articles les plus recents sont mis sur la page thématiques
Le blog Binaire
Le blog du Monde sur l’informatique avec la société informatique de France (SIF).
Contenu Vous y trouverez, des articles de vulgarisation, des entretiens autour de l’informatique et des questions qu’elle soulève. Vous y trouverez aussi la rubrique « Petit binaire » pour les plus jeunes, mais pas seulement…
http://www.21siecle.quebec/ : le numérique et ses implications à destination des non informaticien·nes : Internet, communication, connaissances, le citoyen et la citoyenne, la société.
Tri et recherche
algorithmes de recherche et de tri, complexité algorithmique
jeu du juste prix 0-100
Le Juste Prix Deviner Vous devez rentrer un nombre.
jeu du juste prix 0-1000
Le Juste Prix Deviner Vous devez rentrer un nombre.
data analyse
regression linéaire, prediction, KNN
algorithmique avancé
rendu de monnaie, algorithme glouton
modele OSI
modele en couches, encapsulation, numeros et adresses
protocoles
protocoles IP, TCP, DNS, exercices
TP simulation d’un réseau
du reseau local au reseau internet, adressage, routage, client, serveur, DNS
protocole HTTP
role du navigateur, methodes GET et POST
TP GET POST cookies
formulaire, methode GET POST, outil reseau du dev, navigateur
tuto requests
application des connaissances sur le protocole HTTP, données open source, creer une app en python utilisant des requetes en temps reel
Cours - les bases en python
résumé de cours python
Editeur Turtle
Turtle
Tkinter les bases
Tkinter les bases
Tkinter demineur
Tkinter demineur
IHM python Cours
Du séquentiel à l’événementiel, pygame, fenetre graphique, calques
dictionnaires pour inventaire
utilite des dictionnaires pour mon Escape Game
projet Pygame
projet pygame
images numeriques
format matriciel, module PIL, drapeaux pays
HTML
cours HTML, navigateur, balises
css les bases
les bases en CSS
les bases en javascript
bases en javascript, console javascript, objets, methodes
javascript DOM
javascript dans le code de la page, DOM, variables, types, boucles, procedures, fonctions
serveur Flask
pages web avec server python flask, traitement du formulaire
projet bases en python
chaines str, types simples, boucles, conditions, random
exos tableaux listes python
TP listes, tableaux, matrices
Jeu du Morpion
projet utilisant les tableaux python
Pourquoi écrire des algorithmes? Pour resoudre un problème, comme trier une liste par ordre croissant, un humain y parviendra avec de l’observation, de l’intuition. Il sera peut être difficile d’expliquer sa demarche. Alan Türing (1912-1954), le père de la machine de Türing, cherche à réduire cette part d’intuition en mettant en place un algorithme, qui va guider sa machine, de manière mécanique, jusqu’à la résolution. Les machines n’ont pas d’intuition….
Algorithmes de recherche et de tri
Deux familles d’algorithmes fortement liées:
Algorithmes de recherche: essentiels pour les bases de données. Par exemple: de l’identifiant du client pour retrouver la fiche client. L’algorithme le plus simple est celui de la recherche séquentielle.
Algorithmes de tri: la recherche dichotomique sur une table déjà triée va être beaucoup plus efficace que la recherche sequentielle sur une table non triée
Les 2 méthodes de recherche
Cas n°1: données non triées
Enoncé: Supposons que notre liste contienne des valeurs (des cartes) issues d’un paquet mélangé (non triées). On cherche dans cette liste la carte du 2 de pique. On part de la carte la plus à gauche, et on remonte la liste vers la droite jusqu’à trouver cette carte (ou ne rien trouver si elle n’est pas dans la liste). La fonction de recherche retournera l’indice i si celle-ci est trouvée, -1 sinon. Il s’agit d’une recherche séquentielle.
Cas n°2: données triées
Enoncé: Supposons cette fois que la liste contient cartes triées dans un ordre croissant. On cherche le 2 de carreau. On commence par la valeur (carte) du milieu de la liste. Si la carte du milieu de la liste est supérieure à cette carte, on réduit la liste à sa moitié gauche, et on prend à nouveau l’indice du milieu… On procède ainsi, par elimination de la moitié gauche ou droite de la liste jusqu’à trouver la carte (ou ne pas trouver si celle-ci n’y est pas, et que l’on a reduit le paquet à une seule carte). Il s’agit d’une recherche dichotomique.
Recherche séquentielle
Autre exemple
Imaginez un jeu où votre adversaire doit deviner le nombre que vous avez en tête.
Votre adversaire connait les bornes entre lesquelles vous avez choisi votre nombre.
A chacune de ses propositions, vous lui répondez VRAI ou FAUX, sans autre aide. S’il doit deviner un nombre entre 1 et 100, dans le PIRE des CAS, il peut proposer jusqu’à 100 nombres pour trouver la bonne valeur que vous avez en tête.
Et si la plage de recherche fait n valeurs, le nombre d’essais peut aller jusqu’à n propositions. On dit que la complexité algorithmique pour résoudre ce problème (trouver la valeur en parcourant tous les nombres possibles), est O(n). C’est-à-dire une classe de complexité linéaire. Il existe un algorithme plus efficaces, comme celui de recherche par dichotomie, dont la complexité est O(log(n)).
Cette différence d’efficacité entre fonctions de n (taille du paramètre d’entrée) est d’autant marquée que le nombre n est grand.
Ce problème s’apparente à celui de la recherche séquentielle dans une table:
T: liste d'elements
X: element a trouver dans la liste
Fonction recherche1(X,T)->Booleen:
i = 0
Tant que i < len(T) et T[i] != X:
i = i + 1
Fin
Si i == len(T):
Retourner False
Sinon:
Retourner True
> recherche1(10, [0,2, 4, 6, 8, 10])
True
> recherche2(9, [0,2, 4, 6, 8, 10])
False
Pour l’aider, vous l’aidez à chacun de ses essais en déclarant PLUS (le nombre que vous avez en tête est plus grand), ou MOINS (plus petit).
Une fois que le nombre a été deviné, vous lui annoncez le nombre d’essais. Ce nombre est souvent inférieur au nombre d’essais pour la recherche séquentielle.
L’algorithme que vous utilisez peut s’écrire en langage naturel:
fonctiondevine_un_nombre(borne_inf:entier,borne_sup:entier)->c:entiervarN:entier[borne_inf..borne_sup]<-tirage_aleatoire(borne_inf,borne_sup)varc:entier<-0# compteur du nombre d'essaisvarp:entier[borne_inf..borne_sup]<--1# valeur proposée par l'adversairetantquep!=Nfaire:p<-saisie("quel nombre proposes tu?")c<-c+1sip>Nalors:afficher("c'est moins")sinonsip<Nalors:afficher("c'est plus")sinon:afficher("bravo c'est gagné")finretournerc
Questions:
Faire plusieurs parties avec pour bornes: [0 .. 100]. Quelle est la valeur de c dans chaque cas?
Quelles sont les puissances m et n de 2 qui encadrent la valeur $2^n < 100 < 2^m$?
Jouer à ce même jeu, mais avec les bornes: [0 .. 1000]
Comparer c avec n et m tels que $2^n < 1000 < 2^m$
Le jeu auquel vous avez joué est celui d’une recherche dichotomique. Vous avez cherché un élément (une valeur) dans un ensemble trié (l’ensemble des entiers [0 ..100])
COURS: recherche linéaire
Def: La recherche dans une liste consiste à trouver un élément x dans cette liste, et retourner l’indice de x. Cet algorithme consiste à observer les valeurs de la table, l’une après l’autre, jusqu’à trouver la valeur cherchée x, ou arriver au bout de la table.
Dans le cas d’une table non triée, seul l’algorithme de recherche linéaire est susceptible de donner un resultat.
L’algorithme suivant retourne l’index de x, ou bien -1 si x n’est pas dans la liste.
defrecherche1(T,x)->int:"""
:param T: list of elements
:param x: element
:return: int, index of x in the list
else -1
"""i=0whilei<len(T)andT[i]!=x:i=i+1ifi==len(T):return-1else:returni
Questions
Que retourne l’instruction suivante: recherche1([i for i in range(0,10,2)], 8)?
Que retourne l’instruction suivante: recherche1([i for i in range(0,10,2)], 10)?
Efficacité de la recherche linéaire
Def: L’efficacité est mesurée par la COMPLEXITE: La complexité mesure le nombre d’opérations effectuées par la fonction. Ce nombre d’opérations dépend des valeurs des paramètres, mais aussi de la taille de ces paramètres. C’est pourquoi, il est d’usage de considérer plusieurs cas pour mesurer l’efficacité. Elle est en général exprimée comme une fonciton de n, où n est la taille de la liste passée en paramètre.
Quelles sont les opérations que l’on comptabilise? Pour les algorithmes de recherche, ce sont les opérations de comparaisons, dans la boucle non bornée:
while i < len(T) and T[i] != x
Il y a 2 comparaisons par itération: celle de l’opérateur > et celle de =.
On peut définir ce que l’on appelle le pire des cas. Pour une taille n de la liste, les éléments sont rangés de telle sorte que le nombre d’opérations effectuée est maximum. Pour la recherche linéaire, c’est lorsque l’élément x ne se trouve pas dans la liste.
Dans ce cas, le nombre d’opérations de comparaisons est égal à $2 \times n$. Pour simplifier, on dira que ce nombre d’opérations est égal à n.
La complexité est dite linéaire (proportionnelle à N). Le coefficient $2 \times N$ n’a pas d’importance.
COURS: Recherche dichotomique
Def: La recherche dichotomique est l’algorithme le plus efficace lorsque la table dans laquelle on recherche une valeur est triée. Cette recherche consiste à diviser par 2 l’ensemble de recherche. Pour cela, on définit le milieu de l’intervalle de recherche, puis on conserve:
T[borne_inf : milieu-1] si x < T[milieu]
T[milieu +1 : borne_sup] si x > T[milieu]
comparaison du nombre d'essais. Recherche par dichotomie vs recherche sequentielle. wikipedia
Exemple: On recherche un mot commençant par la lettre c dans un dictionnaire contenant 26 mots. Chaque mot commence par une lettre différente. La première de chaque mot du dictionnaire est dans l’ensemble [a .. z]. Le dictionnaire est trié par ordre lexicographique.
Il s’agit d’une liste du type ['a','b','c','d', ..'m', ..,'x','y','z'].
Comme il s’agit d’une liste dont les indices vont de 0 à 25: Le milieu, c’est 25//2 soit 12. la lettre c a un rang inférieur à 12 (lettre m). Donc, dans une première étape de recherche, on prendra la liste entre les rangs 0 et 11 pour rechercher c.
defrecherche_dicho(T,x):"""
:param T: sorted list of elements
:param x: element
:return: int, index of x in the list
else -1
"""i_min=0i_max=len(T)-1while(i_max>=i_min):mid=(i_min+i_max)//2ifT[mid]==x:returnmidelifT[mid]<x:i_min=mid+1else:i_max=mid-1return-1
Terminaison de la fonction de recherche dichotomique
Dans le pire des cas, l’intervalle va se réduire jusqu’à se limiter à un seul élément. Celui dont l’index est mid. Avec i_min == i_max
Si l’élément recherché est dans la liste: Cet élément est alors la valeur recherchée x, et la fonction se termine en retournant la valeur de l’index de x dans la liste, mid.
Si l’élément recherché n’est pas dans la liste: alors, soit i_min prend la valeur de mid+1, soit i_max prend la valeur de mid-1. On a alors i_min > i_max, qui est la condition d’arrêt de la boucle.
Efficacité de la recherche dichotomique
Le nombre d’opérations de comparaison, dans le pire des cas, est proportionnel à log(n). n étant égal à la taille de la liste. Et log(n) étant egal au nombre de divisions par 2 qu’il faut effectuer pour que n arrive à 1:
Definition: un algorithme de tri permet d’organiser une collection d’objets selon une relation d’ordre. wikipedia.
Nous nous intéressons ici aux méthodes de tri en place: On modifie directement le tableau à trier en permuttant des éléments, sans créer de nouveaux tableaux.
Le tri peut être effectué avec des éléments numériques. Mais il peut aussi être effectué avec des caractères. On parle alors de tri lexicographique.
On a vu deux algorithmes de tri: le tri par insertion, et le tri par selection. Le langage Python possède une fonction de tri native: sorted, et une méthode de tri associée aux listes: sort.
Le tri par insertion
Principe
Principe: Pour cet algorithme, trier, c’est déplacer des éléments, et y insérer l’élément rangé, depuis le debut déjà trié de la liste, jusqu’à la fin. Voir le detail dans le cours de terminale NSI
Exemple d’algorithme
Pour chaque carte de la donne :
Regarder à la fin de la main triée
Mémoriser la clé de cette carte
Tant que la nouvelle carte va avant la carte de la main triée :
Avancer le regard d’une carte vers la gauche dans la main triée
Fin tant que
Insérer la nouvelle carte à gauche de la carte de la main triée qu’on vient de regarder
Fin pour chaque
Question:
représenter la main du joueur lorsqu’il reçoit les cartes 6, puis 9 puis Valet. Il utilise l’algorithme de tri par insertion pour les classer. Il possède au debut de la partie: 8, 10, Dame, Roi, As
Question: quelle partie du programme python correspond à:
Tant que la nouvelle carte va avant la carte de la main triée :
Avancer le regard d’une carte vers la gauche dans la main triée
Efficacité du tri par insertion
La mesure la durée d’execution de l’algorithme pour une liste donnée s’appelle la complexité. C’est une mesure en unités de temps. La complexité depend de la taille de la liste. C’est donc une fonction de n, tel que n = len(L).
Pour expérimenter la mesure de cette durée, aller sur pythontutor.
Puis executer le script pour avoir la mesure du nombre de steps… Cette mesure dépend de l’argument placé dans la fonction range, utilisée pour créer la liste L. Compléter le tableau:
liste L
n
nombre de steps pour trier
L = [chr(i+97) for i in range(3)]
3
30
L = [chr(i+97) for i in range(6)]
6
63
L = [chr(i+97) for i in range(12)]
12
…
L = [chr(i+97) for i in range(24)]
24
…
Analyser alors la fonction steps=f(n)
Question: Ce nombre, augmente t-il de manière régulière avec n? La fonction temps=f(n) est-elle linéaire?
Le tri par selection
Principe: On recherche le plus petit élément dans la partie non triée et on l’insère à la fin de la partie triée.
Exemple d’algorithme
Pour i allant de 1 à n-1 faire:
indmin ← i
Pour j allant de i+1 à n faire:
Si tab[j] < tab[indmin] alors:
indmin ← j
Fin si
Fin pour
min ← tab[indmin]
tab[indmin] ← tab[i]
tab[i] ← min
Fin pour
Questions:
quelle partie de l’algorithme vous fait penser à la recherche du minimum dans une liste?
Comment permute-t-on les valeurs de 2 variables a et b? Faut-il utiliser une variable supplémentaire c? Expliquer. Y-a-t-il une partie du programme qui montre une permutation entre éléments de la liste?
La meilleure complexité que l’on peut attendre pour un algorithme de tri est quasi linéaire. Mais il s’agit d’algorithmes plus élaborés que ceux vus en classe.
Ainsi, pour le tri par insertion, le nombre d’opérations f(N) dépend de la disposition des éléments, tel que:
$$a.N < f(N) < a.N^2$$
La complexité est linéaire dans le meilleur des cas (liste déjà triée), mais quadratique dans le pire des cas (liste triée à l’envers).
Pour le tri par séléction, le nombre d’opérations est constant, et egal à $b.N^2$. La complexité est quadratique.
Le machine learning est l’un des domaines de l’intelligence artificielle. Il s’agit:
d’abord de construire un modèle à partir de données. C’est la phase d’entrainement, ou d’apprentissage.
Puis d’effectuer des prédictions ou prendre des décisions, sur d’autres données.
En apprentissage automatique, on distingue les algorithmes d’apprentissage:
supervisés: apprentissage à partir d’exemples déjà etiquettés (classes discretes ou valeurs Y=f(X) connues)
non supervisées: découverte de la structure de données sans exemples étiquettés.
par réenforcement: système qui augmente ses performances à partir de ses interactions avec l’environnement. Le système va alors modifier les règles de son modèle au fur et à mesure de ces interactions (plutôt catégorisé comme un apprentissage supervisé).
prediction par un modèle de machine learning avec apprentissage supervisé
Analyse données par regression lineaire
Une étude statistique permet de repérer si certains paramètres sont liés entre eux. Alors, si ces données étaient suffisamment nombreuses et précises, il est possible d’établir des lois mathematiques sur ces données. Une manière de représenter ce lien entre paramètres est, par exemple d’établir une loi de regression linéaire.
Régression linéaire
La régression linéaire est un algorithme qui va trouver une droite qui se rapproche le plus possible d’un ensemble de points. Les points représentent les données d’entraînement (Training Set).
Nuage de points avec Regression Lineaire
A partir de données d’entrée, les points oranges (X1,Y1), on cherche s’il existe un modèle mathématique. Par exemple:
$$Y1 = a \times X1 + b$$
Les écarts entre les points et la courbe du modèle devront être les plus petits possibles.
Regression linéaire impossible
Modèle prédictif
Un modèle prédictif ne peut être établi qu’à partir d’une étude prealable de données.
Pour de nouvelles données, on peut alors, grâce à un modèle, prédire le comportement futur du nouvel objet. Faire une estimation, calculer une valeur. A condition que celui-ci fasse partie de la même famille d’objets que ceux qui ont permis d’établir le modèle.
nouvelle donnée d'absisse X1 => Y1 determiné grace au modèle (regression)
Supposons que vous soyez le chef de direction d’une franchise de camions ambulants (Food Trucks). Vous envisagez différentes villes pour ouvrir un nouveau point de vente. La chaîne a déjà des camions dans différentes villes et vous avez des données pour les bénéfices et les populations des villes.
Vous devrez utiliser ces données pour vous aider à choisir la ville pour y ouvrir un nouveau point de vente.
Ce problème est de type apprentissage supervisé modélisable par un algorithme de régression linéaire. Il est de type supervisé car pour chaque ville ayant un certain nombre de population (variable prédictive X), on a le gain effectué dans cette dernière (la variable qu’on cherche à prédire : Y).
Notebook
Vous utiliserez le notebook en ligne sur
Jupyterlite
Algorithme des K proches voisins Knn
Principe
Il s’agit d’un algorithme d’apprentissage supervisé, initialisé par des exemples connus. Pour cela, on part d’un jeu de données existant dont on connait les classes.
L’algorithme KNN (k-nearest neightbors) permet de déterminer à quelle classe appartient un nouvel élément.
Exemple: Les joueurs de NBA
On cherche une correspondance entre les caractéristiques physiques d’un joueur de basket et son poste sur le terrain.
Pour simplifier, on considerera que les postes sont au nombre de trois :
le joueur Centre, noté ‘C’ (position 5 sur le schéma)
Le joueur Ailier, noté ‘F’ (positions 3 et 4 sur le schéma)
Le joueur arrière ou meneur de jeu, noté ‘G’ (positions 1 et 2 sur le schéma)
La ligue de basket americaine contient environ 400 joueurs professionnels. La plupart de nationalité américaine. On dispose d’un extrait de ce fichier (voir dans le dossier datas), constitué de moins de 100 joueurs, classés par ordre alphabetique.
extrait du tableau des joueurs NBA en 2020
Apprentissage supervisé
Chaque joueur de basket occupe un poste particulier sur le terrain:
poste occupé sur le terrain
Une étude des caractéristiques physique des joueurs montre une correlation entre le poids, la taille, et le poste du joueur. Dans un diagramme taille-poids, les joueurs se repartissent en îlots selon leur poste:
les joueurs
Prédiction
On peut alors prévoir le poste d’un nouveau joueur. Pour cela on observe ses k plus proches voisins, et on en déduit quel poste corresspnd à son physique, à partir de la classe majoritairement représentée.
Le joueur semble être à la limite des classes
Méthode:
on ajoute une nouvelle colonne calculée: Pour le joueur inconnu, on calcule la distance avec chaque élément classé dans le tableau .
on trie le tableau selon la distance.
on observe la classe majoritaire pour les k premiers éléments classés de la liste triée. La valeur de k doit être représentative. On prendra la plupart du temps $k = \sqrt N$
Les algorithmes ne peuvent pas resoudre tous les problèmes existants, même si ces problèmes sont bien énoncés mathématiquement. Il n’existe pas non plus une infinité d’algorithmes différents. liste complète de tous les principaux algorithmes (300).
Souvent, c’est le même algorithme qui resoud toute une famille de problèmes. Il suffit d’arranger l’énoncé, de bien identifier les variables d’entrée, d’interpréter convenablement la sortie de l’algorithme.
Par exemple: les énoncés suivants traitent du même problème mathématique:
Rendu de monnaie optimal: Comment rendre 7 euros en utilisant une caisse constituée de pieces ou billets de 5, 2 et 1 euro?
Decoupe optimale d’une barre de fer: Comment réaliser des découpes dans une barre de 7m afin d’optimiser le benefice? Sachant que les clients vont demander des coupes de 5, 2 et 1m. Et que le benefice est plus grand lorsque l’on fait le moins de coupes possible. (voir illustration uliege.be)
Occupation optimale d’une salle de spectacle
…
On verra que pour certains problèmes dits de décision, ou optimisation, la recherche d’une solution peut se faire en écrivant un algorithme. Mais qu’il n’est pas possible d’executer cet algorithme sur une machine en un temps raisonnable.
Le problème du rendu de monnaie
Le problème du rendu de monnaie est un problème d’algorithmique. Il s’énonce de la façon suivante : étant donné un système de monnaie (pièces et billets), comment rendre une somme donnée de façon optimale?
Il existe de nombreuses façons de rendre la monnaie. Mais quelle solution le fera avec le nombre minimal de pièces et billets ?
Par exemple, la meilleure façon de rendre 7 euros est de rendre un billet de 5 et une pièce de 2, même si d’autres façons existent (rendre 7 pièces de un euro, par exemple).
Image by pixabay conmongt-1226108
algorithme naif
Une première idée, naïve serait de commencer par rendre la piece de plus grande valeur, puis sur la somme restante, la pièce la plus grande possible (de valeur inferieure ou egale), et ainsi de suite.
S’entrainer à rendre la monnaie de manière optimale:
Cliquer pour lancer l'animation
Programmation Python
Pour une somme à rendre, et un systeme de monnaie appelé caisse, contenant par exemple la liste[20, 10, 5, 1]:
soit la piece est inférieure à la somme à rendre: alors on soustrait la piece à la somme à rendre et on continue avec cette même caisse, et la nouvelle somme à rendre.
soit la piece est supérieure à la somme à rendre. on retire la piece de la caisse. Et on continue pour faire diminuer la somme à rendre.
Méthode utilisant une liste pour la variable rendu
Quelques essais avec le script précédent montrent que le rendu n’est pas toujours optimal. Il faut envisager d’autres possibilités pour rendre la monnaie.
Une autre méthode pourrait être d’envisager TOUTES les combinaisons. On pourrait alors imaginer que l’on commence par rendre la monnaie avec une des pieces de la caisse (pas forcément la plus haute), puis on choisit une autre piece possible (egale ou moins haute), … Jusqu’à ce que la somme à rendre soit nulle. On envisage ainsi toutes les combinaisons possibles, ce qui, avec une valeur élevée de la somme à rendre, et un grand nombre de pieces dans la caisse, va donner un très grand nombre de combinaisons. On selectionne enfin la meilleure des solutions (celle optimale).
Par exemple, pour rendre 7 euros, voici toutes les combinaisons possibles (la solution optimale étant la première):
5 + 2
5 + 1 + 1
2 + 2 + 2 + 1
2 + 2 + 1 + 1 + 1
2 + 1 + 1 + 1 + 1 + 1
1 + 1 + 1 + 1 + 1 + 1 + 1
Un programme python exprimerait le rendu sous forme de liste:
Parfois la solution est impossible à trouver, il n’y a pas de rendu possible avec la caisse considérée: V / F
La solution dépend de l’ordre des pieces dans la caisse: V / F
La solution est toujours optimale en commençant par rendre la monnaie avec la plus grande piece, puis la piece moins grande, etc…: V / F
Avec la 2e méthode, celle de recherche exhaustive: cette méthode permet de tester toutes les possibilités, toutes les combinaisons possibles pour le rendu de monnaie: V / F
Supposons que le programme, pour la méthode 2, commence par calculer le rendu pour pour la somme 7 avec la combinaison [5,2]. Plus loin, dans le programme, il calcule une autre solution pour rendre 7, et commence avec la combinaison [1,1,1]. Doit-il aller au bout du calcul de la solution avec cette combinaison, ou bien, peut-il arrêter son calcul au milieu? Cela est-il réalisé par le programme, tel que vous l’avez écrit?
Conclusion
En analysant les 2 méthodes précédentes, on voit que le rendu de monnaie sera optimal pour toute somme à rendre, et pour tout type de caisse, à condition de tester toutes les combinaisons de rendu possible. Puis de selectionner la meilleure.
Cela risque toutefois de générer un programme dont la complexité va être très divergente. Avec une quantité d’opérations à effectuer qui peut largement depasser les capacités des machines actuelles (la durée d’execution pourrait exceder la durée de vie d’un être humain): clogique.fr
Les algorithmes de recherche exhaustive sont de complexité exponentielle. La durée d’execution (relative à la complexité) s’exprime selon une loi dependante de la taille du-des paramètre-s d’entrée. La loi exponentielle est la plus divergente:
comparaison de la divergence de quelques fonctions
On verra qu’il existe des méthodes de programmation qui resolvent ce type de problème avec plus d’efficacité, sans pour autant donner systematiquement la solution la plus optimale.
Liens
Suite du cours, programmation dynamique, classe d’algorithmes de decision: Term NSI
illustrations des problèmes classiques resolus par algorithme glouton/force brute: uliege.be
TP3: Programmes plus evolués, de python à l’assembleur: Lien
L’Histoire de l’Ordinateur
En 1623 Wilhelm Schickard ou bien Blaise Pascal en 1642 créent des machines munies de rouages mécaniques pour faire des additions et des soustractions. Il ne s’agit pas encore d’ordinateurs, car celles-ci n’ont qu’une seule fonction.
En 1854 le mathématicien britannique George Boole créé le calcul propositionnel. Aujourd’hui, l’algèbre de Boole trouve de nombreuses applications en informatique et dans la conception des circuits électroniques.
Elle fut utilisée la première fois pour les circuits de commutation téléphonique par Claude Shannon.
Alan Türing a discuté longuement avec Claude Shannon. Cela a pu influencer ses reflexions sur le rôle des machines. Il est à l’origine de la conception du traitement automatisé de l’information par une machine. John Von Neumann va proposer l’architecture d’une machine universelle sur laquelle reposent tous les ordinateurs. Leur point commun: ils sont tous capables de traiter de la même manière les calculs sur des nombres ou des propositions, exprimés en binaire.
La premiere machine universelle
1834 La première machine sur le modèle d’un ordinateur. La machine analytique (analytical engine, Charles Babbage: 1791-1871) est une machine à calculer programmable imaginée par le mathématicien anglais Charles Babbage. Il ne la réalisera jamais (sauf pour un prototype inachevé), mais il passera le reste de sa vie à la concevoir dans les moindres détails. La machine analytique reprend les différentes parties de nos ordinateurs actuels:
Une unité centrale
Une mémoire
Un lecteur de cartes des métiers à tisser Jacquard (l’équivalent d’un périphérique d’entrée)
Une imprimante (un périphérique de sortie).
La machine fonctionne en 5 étapes:
reçoit les opérations demandées des cartes,
gère le transfert des nombres et leur mise en place dans le bon ordre,
C’est la première machine Türing-complète. Sauf que celle-ci ne manipule pas les données en binaire.
Prototype (1871) non terminé de la machine analytique de Babbage, exposée au
C’est son élève, Ada Lovelace qui formalise les idées de Babbage et développe le premier algorithme de programmation de l’histoire, devenant la première informaticienne de l’humanité.
Des machines pour chiffrer et decrypter des informations
La période de la seconde guerre mondiale a vu emerger des machines électromecaniques plus efficaces que celles mécaniques.
Ces machines ne sont pas Türing-complètes.
1938-1943 La Bombe, un supercalculateur est utilisé pour le décryptage d’[Enigma](https://fr.wikipedia.org/wiki/Enigma_(machine), une machine utilisant un système de rotors pour produire un chiffrement mécanique. Les anglais, français et polonais travaillent sur le déchiffrage en testant des combinaisons. La Bombe a été conçue pour les attaques de force brute. Cette machine abat par jour le travail de dix mille décrypteurs. C’est le mathematicien Alan Turing qui parvient à casser le chiffre grâce à l’utilisation d’une version améliorée de cette machine.
La Bombe - version britannique
1943-1945 Les machines du projet Colossus permettent de décrypter les machines de Lorentz. Le premier, Colossus Mark 1, est opérationnel en décembre 1943: constitué de 1500 tubes à vide, il accomplissait 5000 opérations par seconde.
Colossus Mark2. Le panneau incliné à gauche sert
Le chiffrement Lorenz est beaucoup moins connu que celui d’Enigma. Il était utilisé par les hauts dirigeants allemands pour communiquer entre eux alors qu’Enigma était utilisée au quotidien pour les autres types de communication.
Colossus n’est pas une machine universelle, mais c’est bien le premier processeur électronique, numérique, et partiellement programmable de l’histoire. Cette machine montre que l’électronique peut être utilisé pour le traitement numérique à grande vitesse.
Vers 1940 plusieurs spécialistes développent des calculateurs à programme externe, suivant le projet de machine analytique de Babbage, en y incluant des relais électriques: Zuse, Coufignal, Aiken, Stibitz… Ces machines utilisaient des cartes ou rubans perforés, et étaient donc des calculateurs à programme externe.
Aucun n’avait eu l’idée d’une machine à programme enregistré, concept essentiel pour les machines électroniques.
Machines électromécaniques dans la lignée conceptuelle de Babbage
1938 le Z1, 1941 le Z3 (Konrad Zuse), est un ordinateur électromécanique utilisant le système binaire et lisant son programme sur une bande perforée. Le Z3 contenait plus de 2000 relais électromécaniques, pesait une Tonne et consommait plus de 4kW. Il comprend une mémoire, un dispositif de contrôle et une unité arithmétique calculant en binaire sur des nombres à virgule flottante! Les données et les instructions sont perforées sur du film de cinema, plus solide que des rubans en papier. Il était capable d’effectuer une addition en 0,8 s. Sa fréquence était de 5,3 Hertz, assez lente à cause des relais. A l’epoque, aucun appareil ne pouvait rivaliser.
Z3: the First Functional Programm-Controlled Automatic Calculating Machine -
L’institut de recherche aéronautique allemand l’utilisait pour réaliser des analyses statistiques sur les vibrations des ailes.
Zuse était le premier à concevoir que les fonctions de contrôle pouvaient aussi s’exprimer et être stockées sous forme numérique, donc à créer une machine programmable. Ce qui permettait de changer de programme sans avoir à modifier les connexions.
Si Ada Lovelace, élève de Babbage, fut la première programmeuse théorique d’une machine inexistante, Zuse fut pour sa part le premier programmeur d’une machine réelle en pratique.
Les calculateurs géants
Les premiers ordinateurs étaient des machines électromecaniques, fabriquées à l’unité après des années de recherche et developpement. Leur taille était immense, de même que leur consommation électrique. Le temps passé à leur maintenance et réparation était important (plus de 50%). Leur programmation était très rudimentaire, et leurs pannes, fréquentes.
On ne pouvait pas implémenter des algorithmes trop complexes. Même s’il s’agissait, formellement, de machine universelle. Ils repondaient alors à un besoin de calculer.
Les opérations à réaliser sont entrées à la main. Les données sont lues sur une carte perforée.
Ces machines ont d’autres defauts:
il n’y a pas de distinction entre la fonction mémoire et la fonction calcul.
pas d’unité centrale généraliste, mais une juxtaposition d’accumulateurs et d’unités spécialisées
la programmation se fait par cablage ou en positionnant des interrupteurs. Ces machines nécessitent que l’on change leur câblage à chaque type d’opération.
illustration de la différence entre supercalculateurs
année
machine
unité logique
vitesse de calcul
remarques
1944
calculateur Harvard Mark 1 (IBM)
3300 relais
3 addition sur 23 chiffres par s
1945
ENIAC
1800 tubes (technologie superieure aux relais)
5000 additions par s
a servi à calculer la faisabilité de la bombe H
1948
EDSAC
lignes à retard sur mercure
programme écrit en binaire
1951
UNIVAC
5 200 tubes à vide
1 905 opérations par seconde
utilisé par CBS pour prédire l’issue de l’élection présidentielle de 1952. 13 tonnes. consomme 125 kW. L’unité accueillant la mémoire à mercure fait 4,3 m × 2,4 m × 2,6 m à elle seule. Le système au complet occupe 35,5 mètres carrés.
1962
Atlas (Manchester)
Les 96 ko de mémoire, réalisée en tores de ferrite étaient étendus à l’aide des 576 ko stockés sur tambour magnétique
1964
CDC 6600
entre 1 et 10 mégaflops (millions d’opérations par s)
Remarque: l’ENIAC sera améliorée en 1948: elle intègre alors la notion d’instruction et de programme, ce qui correspond au modèle classique d’ordinateur à programme enregistré.
C’est aussi le premier ordinateur binaire, ne comportant plus de pièces mécaniques. (Mauchly et Eckert).
Il exécute son premier programme le 12 avril, et son premier programme de production le 17 avril. La simulation de Monté Carlo exécutée le 12 avril 1948 par l’ENIAC est la plus ancienne trace de programme enregistré connue à ce jour.
Les premiers ordinateurs fabriqués en série
IBM 650, le premier ordinateur fabriqué en série (1955)
Cet ordinateur n’a pas encore de transistors mais des tubes à vide.
IBM 7090, le premier ordinateur à transistors (1959)
Machines universelles
1945 En tirant les conclusions de réalisations électroniques secrètes menées pendant la guerre, deux documents apparaissent et definissent ce que l’on nommera ordinateur, le calculateur numérique à programme enregistré. Les motivations des deux hommes sont différentes:
John Von Neumann: qui cherche à developper des moyens pour les Universités pour leurs besoins de calculs mathématiques.
Alan Turing: qui veut réaliser une machine à traiter les informations.
La contribution de Turing à l’avènement des ordinateurs
Le binaire
Contrairement à Babbage, Türing se rend compte que les opérations arithmétiques ordinaires peuvent être traduites dans le cadre de la logique booléenne, sous forme de circuits logiques (booléens). Il conçoit comme première machine un multiplicateur booléen électrique.
Il prolonge l’idée de Gödel de coder les opérateurs, les instructions , et les fonctions (des propositions) par des nombres entiers.
Traiter des instructions revient à calculer sur des nombres entiers, écrits en binaires.
Les algorithmes
Le raisonnement mathématique est une combinaison:
d’intuition
d’ingéniosité, de procédures
L’idée de Türing est de diminuer la part d’intuition et d’augmenter celle de procédure.
Par exemple, lorsque l’on réalise une opération de tri, on le fait d’abord de manière intuitive. Pour qu’une machine soit capable de le réaliser, il faudra en dégager une procédure.
Machine de Türing
C’est une machine mathématique permettant la manipulation réglée de signes.
Son rôle est de transformer les symboles fournis en entrée, en symboles lisibles en sortie.
Cette machine utilise les instructions d’un programme (une tables d’états) et repère un état d’un registre, états qui définissent les étapes de l’algorithme.
C’est une machine conceptuelle, qui a permi de définir ce qu’est un problème calculable.
Une machine de Tûring est conçue pour résoudre une classe de problèmes donnés: si une machine de Türing est programmée pour résoudre un opération d’addition, alors elle pourra résoudre TOUTES les opérations d’addition, quelles que soient les données en entrée.
Une machine de Türing particulière contient donc, par avance, un programme.
Une machine de Türing universelle est capable de résoudre TOUS les problèmes possibles de toutes les machines de Türing possibles (contient tous les programmes existants ou à venir).
John Von Neumann fait référence de manière explicite à ce concept lorsqu’il présente l’architecture à laquelle doivent se conformer les machines universelles:
Un ordinateur se définit comme une instance matérielle, concrète, d’une Machine de Turing Universelle
Calculabilité
Si un problème (proposition, fonction), que l’on peut énoncer sous forme mathématique, peut être résolu par une machine de Tûring, alors celui-ci est calculable. Il doit exister un nombre fini d’instructions pour résoudre ce problème.
Comparer des programmes
Il devrait être possible de comparer des programmes en construction en évaluant le nombre de pas de calcul qui serait nécessaire. Tûring fait émerger la notion de compléxité.
John Von Neumann (1945) est le concepteur de l’architecture de la machine universelle et de ses différents dispositifs:
processeur
mémoires
dispositifs d’entrée/sortie
Il est à l’origine du concept de programme enregistré: le stockage des données et des instructions sous forme d’impulsions électriques à l’intérieur même de la machine qui pourra les consulter à l’instant et à la vitesse qui lui convient. En remplacement du traitement mécanique alors utilisé, ce qui necessitait une vaste manipulation de cables et de boutons à placer sur la bonne position pour specifier le nouveau problème. Charles Babbage avait déjà eut cette idée un siècle plus tôt.
illustration de la différence entre supercalculateurs
Cette architecture s’oppose à celle de Harvard (mémoires différentes pour les données et les programmes) du Mark1.
Von Neumann est également le concepteur de l’ordinateur IAS à Princeton.
Le stockage était alors réalisé par des tubes cathodiques, chacun de 1024 bits.
Dans l’architecture de Von Neumann, un ordinateur est constitué de quatre parties distinctes:
Le CPU: Central Processing Unit (unité centrale de traitement) appelé aussi processeur;
La mémoire où sont stockés les données et les programmes. La mémoire se divise entre:
une mémoire volatile (RAM ou mémoire vive) qui gère les programmes et les données
une mémoire permanente (ROM) qui gère les programmes de base de la machine.
des bus qui sont des fils conduisant des impulsions électriques et qui relient les différents composants;
des entrées-sorties (E/S ou I/O input/Output) pour échanger avec l’exterieur.
Les échanges entre la mémoire et les registres du CPU se font via les bus selon une chronologie séquencée par l’horloge et suivant la nature des échanges: données ou adresse. Cette horloge est externe au processeur.
Un programme est une suite d’instructions codées sous forme binaire. Il précise la suite d’instructions exécutées par l’ordinateur. Ces instructions, codées en binaire peuvent être exprimées pour un humain en langage assembleur, le langage de plus bas niveau (une traduction mnémonique du binaire).
Le processeur CPU
L’unité de traitement est un circuit qui s’occupe de faire des calculs et de manipuler l’information provenant des entrées-sorties ou récupérée dans la mémoire. Dans les ordinateurs, l’unité de traitement porte le nom de processeur, ou encore de Central Processing Unit, abrévié en CPU. Tout processeur est conçu pour effectuer un nombre limité d’opérations bien précises, comme des calculs, des échanges de données avec la mémoire, etc.
Les processeurs multicœurs: regroupement de plusieurs processeurs dans le même boitier. Un processeurs multicœurs, contient plusieurs cœurs, chaque cœur pouvant exécuter un programme tout seul. Chaque coeur contient un séquenceur d’instruction, des registres, une unité de calcul. Mais il manque certains circuits dédiés au processeur principal, comme les circuits de communication avec la mémoire. Les systemes d’exploitation se sont adaptés à cette nouvelle architecture. Un processus peut lancer plusieurs threads, partagés sur les différents coeurs.
Pour calculer plus rapidement, le processeur utilise une mémoire plus rapide que la RAM: Les caches, qui sont des mémoires intermédiaires entre les registres internes du micro-processeur et la mémoires vive.
Pour un processeur multicoeur, certains caches sont dédié à chaque “coeur”, d’autres sont partagés. wikipedia - multicoeur
cache dédié / cache partagé
La puissance de la machine augmente significativement en élevant la fréquence de calcul, supérieure à celle d’un processeur monocœur. Mais cette méthode a ses limites: En effet, l’augmentation de fréquence d’un processeur cause rapidement des problèmes de surchauffe.
Les coprocesseurs: Ce sont des processeurs qui complètent un processeur principal pour certaines fonctions wikipedia:
des coprocesseurs arithmétiques: assurent certains types de calculs que ne peuvent pas realiser le processeur principal (division entiere, flottante, racines carées…). Par exemple sur la Nitendo DS.
coprocesseurs pour le rendu 2D/3D et les coprocesseurs sonores: sur les anciennes consoles de jeux vidéo, comme La Nintendo 64, la Playstation et autres consoles de cette génération ou antérieure.
coprocesseurs pour l’accès aux périphériques: L’accès aux périphériques peut demander beaucoup de puissance de calculs. La Nintendo 3DS disposait d’un processeur principal de type ARM9, du coprocesseur pour les divisions, et d’un second processeur ARM7. L’ARM 7 était le seul à communiquer avec les périphériques et les entrées-sorties.
mémoires ROM et RWM
Les mémoires ROM stockent des programmes à exécuter et sont lues directement par le processeur. Pour les mémoires RWM ou RAM, on peut y acceder en lecture et écriture.
Les RWM stockent les variables du programme à exécuter, des données que le programme va manipuler. Selon l’architecture de la machine, le programme peut être entièrement stocké dans la ROM, ou bien être partagé entre la ROM et la RWM.
adressage differencié ou commun pour les mémoires - source : wikibooks
Les bus
Les données doivent circuler entre les différentes parties d’un ordinateur, notamment entre la mémoire vive et le CPU. Le système permettant cette circulation est appelé bus. Il existe, sans entrer dans les détails, 3 grands types de bus: adresses, données, de contrôle.
Les péripheriques
Les périphériques sont très divers. On les classe en périphérique d’entrée, sortie, entrée-sortie.
Toutes les entrées-sorties contiennent des registres d’interfaçage, qui permettent de faire l’intermédiaire entre le périphérique et le reste de l’ordinateur. source:wikipedia
registres d’interfaçage - wikipedia
Loi de Moore
Des années 1970 aux années 2000, la miniaturisation des circuits a suivi al Loi de Moore qui prédit un doublement du nombre de transistors par cm2 tous les 18 mois. Cette miniaturisation et l’augmentation des fréquences d’horloge (qui ont aussi doublé environ tous les 18 mois) ont permis d’augmenter la puissance des processeurs de façon exponentielle pendant près de 40 ans.
La figure suivante montre l’évolution du nombre de transistors pour un même élement de surface: source-wikipedia
illustration de la loi de Moore - source wikipedia
L’image ci-dessous illustre, elle, l’evolution de la finesse de gravure
illustration de la finesse de gravure dans le temps - source eskool.gitlab.io/
Architecture Von Neumann vs Harvard
La différence de ces architectures repose sur la gestion des mémoires pour les programmes et données:
Von Neumann: un même support (RWM) contient programme et données pour les processus en cours. Les instructions des programmes sont dupliquées dans la RAM. Elles existent alors à 2 endroits distincts de la machine: dans la mémoire de masse (persistante) du systeme, mais aussi dans la RAM. Il serait assez inefficace d’executer le programme depuis la mémoire de masse, car celle-ci est beaucoup plus lente.
Harvard: Données dans une mémoire de travail différente de la RAM (mémoire flash) utilisée pour les programmes. Pas de duplication du programme. Economie des supports de stockage, et economie d’énergie.
Voir la video suivante expliquant la différence entre ces 2 architectures:
MooC Arduino #4 - Architecture de Von-Neumann, Harvard et Microcontrôleurs
L’architecture Harvard est utilisée pour les microcontrôleurs, pour lesquels le besoin de miniaturisation amène à intégrer tous les composants internes dans une même puce (onchip). Les microcontrôleurs embarquent une mémoire de type EEPROM (electrically erasable programmable read only memory 64-256ko), suffisement rapide d’accès pour l’utiliser directement, et sans avoir besoin de charger le programme dans une nouvelle RAM.
La machine avec architecture Harvard peut aussi gérer une mémoire de masse (persistante) comme un disque dur, ou carte flash externe. Il s’agit alors d’une extension, utile pour augmenter la capacité de la mémoire flash interne, qui est souvent réduite.
Un Circuit intégré, c’est un circuit électronique conventionnel qui a été mis sur une plaque de silicium de quelques $cm^2$. La consommation électrique, et l’echauffement sont beaucoup inférieurs, et la qualité bien supérieure en rapport aux premieres machines qui n’en disposaient pas. Cela a permis une diminution du coût.
Un « système sur une puce » est un système complet embarqué sur une seule puce (“circuit intégré”), comprenant de la mémoire, un ou plusieurs microprocesseurs, des périphériques d’interface (processeur graphique GPU…), et autres composants nécessaires à la composition du SoC complet…
Ces systèmes permettent de réduire l’encombrement, la consommation d’énergie (courants faibles), et de diminuer le coût de production (gros volumes de fabrication). L’inconvenient principal est qu’il est n’est pas possible de modifier soi-même ses composants, et de l’upgrader.
TP3: Programmes plus evolués, de python à l’assembleur: Lien
Qu’est ce qu’un ordinateur?
Un ordinateur est une machine qui traite de l’information, stockée dans la mémoire, à l’aide du processeur. Les instructions de ces traitements sont aussi stockés dans la mémoire, sous forme de programmes.
Il existe donc une très grande variété de machines que l’on peut appeler des ordinateurs: celles présentes dans une PC de bureau, dans un mac, dans un smartphone, un objet connecté, une voiture…
Rappels sur l’architecture Von Neumann
Dans l’architecture Von Neumann:
une machine universelle est contrôlée par un programme.
Les données et programmes sont écrits sur une même mémoire (en binaire). L’ordinateur enregistre les instructions des programmes qu’il exécute dans sa mémoire vive.
Les instructions sont executée de manière séquentielle, par un processeur.
Les mémoires RAM d’une part et les mémoires non volatiles d’autre part (Disques durs, mémoires flash) sont reliées au processeur (donc aux registres du processeur) par une liaison appelée Bus. En réalité, seule la RAM est directement accessible au processeur.
Description d’un ordinateur avec microprocesseur
En video
Fonctionnement d'un ordinateur - Mooc Architecture
à l’echelle de la carte mère
La carte mère d’un ordinateur comprend:
un microprocesseur
de la mémoire volatile (random access memory, RAM)
de la mémoire de masse
des ports:
port ethernet, RJ45
port USB
ports pour carte wifi, carte son, carte graphique, …
des périphériques d’entrée et sortie: écran, haut-parleur, souris, clavier…
Ces périphériques sont connectés aux 3 Bus définis plus loin et se comportent comme une mémoire. On leur affecte des adresses (différentes de celles de la RAM) et on communique avec eux en écrivant à ces adresses. Le Bus de contrôle va detecter un changement sur l’une de ces adresses et interrompre le traitement en cours.
Certains ports vont ajouter des extensions à l’ordinateur (carte son, video, wifi). Certains vont être essentiels au fonctionnement de l’ordinateur (mémoires).
Liaisons entre composants: les Bus
Il existe des Bus de différentes nature pour relier les composants:
bus d’adresse: permet au processeur d’indiquer à la mémoire l’emplacement pour lire/écrire.
bus de données: transporte les données entre la mémoire et le processeur.
bus de contrôle: permet de coordonner le fonctionnement du processeur et de la mémoire.
Les bus peuvent être bi-directionnels: les données transitent dans les 2 sens. Mais aussi directionnel: c’est le cas du bus d’adresse entre le processeur et la RAM, qui n’est parcouru que dans le sens processeur => RAM.
à l’echelle des composants
Les constituants de l’ordinateur sont composés de circuits intégrés. On trouve 2 grandes catégories de circuits intégrés:
les circuits combinatoires: l’état de sortie de ces circuits ne dépend que des états d’entrée.
les circuits séquentiels: l’état de sortie dépend des états d’entrée, mais aussi de l’état courant du circuit. Ces circuits peuvent ainsi stocker une valeur appelée état courant. Les registres sont typiquement des circuits intégrant des circuits séquentiels.
CPU et MCU: des architectures différentes
Certaines machines comportent des composants séparés sur la carte mère. Le microprocesseur (CPU) est relié aux autres composants par des bus.
Pour d’autres machines, comportant microcontrôleur (MCU), les composants occupent une même puce (un même chip). Ces machines sont moins chères et consomment moins d’électricité.
L’architecture d’un processeur (CPU) comporte 2 parties:
L’UC: C’est l’unité de commande, UC, qui traduit chacune des instructions successives du programme en opérations élémentaires. C’est cette partie du processeur qui est chargée d’obtenir les instructions successives du programme et de les executer. L’UC contient:
le registre Program Counter, PC
le registre d’instruction RI
une horloge.
La partie opérative qui comprend les outils permettent de réaliser les actions élémentaires ordonnés par l’UC. Cette unité de traitement est constituée de:
l’UAL (Unité Arithmétique et Logique) qui réalise les opérations arithmétiques sur des entiers.
des registres internes, pour stocker de manière très provisoire les retenues des calculs par exemple.
L’UC traite une séquence d’instructions, alors que l’UAL traite une séquence de données. L’UC est chargée de la reconnaissance des instructions et de leur exécution par l’unité de traitement au rythme de l’horloge.
Le cycle Von Neumann
Le processeur réalise le cycle de Von Neumann:
Lire une case mémoire d’adresse PC (envoyer l’adresse à la mémoire, et recevoir en retour la donnée à cette adresse).
Interpréter cette donnée comme une instruction, et l’exécuter
Ajouter 1 au program Counter (PC), qui stocke l’adresse de la prochaine instruction.
Recommencer
Détail d’un cycle d’execution
Important:
Le processeur ne manipule pas directement les données mais leurs adresses.
Des registres servent à lire et écrire les données en mémoire. Ce sont les registres d’adresse et de données.
Utilisation des registres en lecture: rôle de l’unité de contrôle
registre d’adresse: stocke l’adresse de la donnée, avant d’envoyer le signal de lecture
registre de données: la mémoire va chercher le contenu de l’adresse qui lui est envoyée, et retourne la donnée vers le registre de données.
La donnée peut être interprétée comme une instruction. Celle-ci est alors décomposée en un code d’opération (OP) ainsi qu’en 2 opérandes, qui sont les adresses d’une données (A et B). OP, A et B sont stockés dans le registre d’instruction (RI).
Execution de l’opération: rôle de l’unité de traitement
La figure ci-contre représente un schéma classique d’UAL. Celle-ci possède deux entrées A et B sur lesquelles on présente les données à traiter. L’entrée F désigne l’opération à effectuer (vient du code OP). Source: wikipedia - Unité Arithmétique et Logique
Enfin, l’UAL possède deux sorties, R qui est le résultat de l’opération, et D les éventuels drapeaux. (information d’erreur ou de dépassement)
UAL - Unité Arithmétique et Logique
Utilisation en écriture
registre d’adresse: envoie à la mémoire l’adresse pour l’écriture
registre de données: envoie la donnée à la mémoire, qui va écrire celle-ci à l’adresse reçue.
TP3: Programmes plus evolués, de python à l’assembleur: Lien
Le langage assembleur
Le langage assembleur est, en programmation informatique, le langage de plus bas niveau qui représente le langage machine sous une forme lisible par un humain. (wiki)
L’assembleur oblige à programmer la gestion des mémoires:
Pour échanger des données avec la mémoire, le processeur transfert l’état d’un registre dans une case mémoire (STR) ou l’état d’une case mémoire dans un registre (LDR). On rappelle que la mémoire contient à la fois les instructions et les données. Mais les calculs du processeur se font sur les registres. Il faut donc prévoir de charger les valeurs de la RAM vers les registres avant de faire une opération.
D’ailleurs, une instruction machine est une chaine binaire composée de 2 parties:
un champ “code opération” qui indique au processeur le type de traitement à effectuer.
un champ opérande qui indique l’adresse des données.
Le simulateur
Lancer le simulateur
clic droit > ouvrir dans un nouvel onglet pour lancer le simulateur ARM
Les 3 familles d’instructions machine
Ce sont les instructions:
de transfert de données
arithmétiques
de rupture de séquence
Transfert de données
Les opérations de transfert se font d’un registre vers un emplacement mémoire, ou l’inverse.
Ordre
Instruction
Description en langage naturel
Affectation (variable)
x: 23
Place 23 dans la variable x, c’est à dire 23 dans l’emplacement RAM prévu pour x
Affectation (registre)
MOV R1, #23
Place la valeur 23 dans le registre R1
Charger
LDR R1, 78
LOAD: Place dans le registre R1 la valeur stockée à l’emplacement 78 de la RAM
Stocker
STR R1, 151
STORE: Place dans la RAM à l’emplacement 151, la valeur stockée dans le registre R1
Stocker
STR R1, x
STORE: Place dans la RAM à l’emplacement prévu pour x, la valeur stockée dans le registre R1
Exemple 1:
Le programme suivant affecte une valeur dans un registre, puis la copie dans la RAM.
MOV R0, #16
STR R0, 55
HALT
Copier-coller le script, assembler. Régler le bouton OPTIONS sur hex
question b: Combien de lignes fait le programme? Quelles sont les adresses dans la RAM des instructions (donner la somme colonne + ligne)?
Dérouler le script pas à pas (appuis successifs sur STEP)
question c: Quel est le registre utilisé? Quelle est la valeur déplacée? Quelle adresse de la RAM va contenir la valeur à stocker?
question d: Si l’on suppose que la complexité temporelle est égale au nombre de fois qu’il faut appuyer sur le bouton STEP pour arriver à la dernière ligne du programme: Quelle est la compléxité de ce programme?
Exemple 2: Programme mystère
Dans un programme en assembleur, il sera plus facile de manipuler des variables que des adresses mémoires.
LDR R0, x
LDR R1, y
STR R0, y
STR R1, x
HALT
0
0
0
x: 23
y: 18
Copier-coller le script, assembler.
question a: Vérifier que 23 (base 10) = 17 (base 16), et que 18 (base 10) = 12 (base 16).
question b: Combien de lignes fait le programme? Quelles sont les adresses dans la RAM des instructions (donner la somme colonne + ligne)? Quelles sont les adresses RAM des données?
Dérouler le programme à vitesse réduite.
question c: Interpréter les lignes 0 à 4 du programme (donner une explication en langage naturel). Que fait le programme mystère?
Arithmétique
Ce sont les opérations courantes (addition, soustraction, multiplication par 2, division par 2). Elles se font depuis un registre, vers un autre registre.
Voici une liste non exaustive des instructions du
simulateur ARM
Les instructions de traitement suivantes concernent uniquement les registres.
L’un de ces registres est le Program Counter, PC. Celui-ci repère l’état courant dans le programme (la ligne du script à executer).
Ordre
Instruction
Description en langage naturel
Ajouter
ADD R0, R1, #16
Ajoute 16 à R1 et place le résultat dans R0
Ajouter
ADD R0, R0, R1
Ajoute R1 à R0 et place le résultat dans R0
Soustraire
SUB R0, R0, #16
Soustrait 16 à R0 et place le résultat dans R0
Ajouter
ADD R0, R1, #16
Ajoute 16 à R1 et place le résultat dans R0
Multiplier par 2
LSL R0, R0, #1
déplace les bits de R0 d’un seul rang (#1) vers la gauche et place dans R0
Diviser par 2
LSR R0, R0, #1
déplace les bits de R0 d’un seul rang (#1) vers la droite et place dans R0
Exemple 3 add: programme qui ajoute 2 nombres entrés par l’utilisateur
INP R0,2: attend un nombre en entrée.
OUT Rd, nombre: affiche à l’écran. out Rd,4 affiche un nombre signé ou non(Rd,5). Rd,6 affiche en hexadécimal et Rd,7 affiche un caractère.
INP R0,2
INP R1,2
ADD R2,R1,R0
OUT R2,4
HALT
question a: Ce programme, permet-il d’additionner des nombres relatifs, comme par exemple: $123 + (-145)$? Quelle est alors la représentation binaire de $-145$?
question b: Recopier sur votre cahier le script correspondant en python:
x=int(input('entrer la valeur de x'))y=int(input('entrer la valeur de y'))x=x+yprint(x)
question c: Compléter le programme assembleur qui multiplie par 2 le nombre saisi par l’utilisateur (avec LSL), affiche le résultat, et le stocke dans la RAM à l’emplacement 10.
INP R0,2
LSL R0, R0, ...
OUT R0, 4
STR ..., ...
question d: Ecrire dans votre cahier le script correspondant en python.
Rupture de séquence
Les ruptures de séquence utilisent des étiquettes, à définir dans le programme. Le programme va alors s’executer normalement, ligne après ligne, sauf si un branchement l’amène à une ligne, portant une etiquette.
HALT: arrêt du programme
CMP Ri, Rj: effectue la comparaison entre Ri et Rj. Attention, cette instruction ne traite pas le résultat de la comparaison! C’est le rôle de la commande suivante.
B ou BGT, … sont les opérations de branchement
plus grand que: On utilise une combinaison de 2 lignes pour effectuer le test si R1 > R2 aller à la ligne label:
CMP R1, R2
BGT label
plus petit que: On utilise une combinaison de 2 lignes pour effectuer le test si R1 < R2 aller à la ligne label:
CMP R1, R2
BLT label
est egal à: On utilise une combinaison de 2 lignes pour effectuer le test si R1 == R2 aller à la ligne label:
CMP R1, R2
BEQ label
aller systematiquement à:B label va obliger à toujours revenir à la ligne d’etiquette label
La liste complète des instructions se trouve à la page INFO accessible depuis le bouton info du simulateur.
Exemple 4 max: programme qui retourne le plus grand des 2 nombres saisis par l’utilisateur
Ce programme peut être directement chargé depuis le bouton SELECT du simulateur.
0 INP R0,2
1 INP R1,2
2 CMP R1,R0
3 BGT HIGHER
4 OUT R0,4
5 B DONE
HIGHER:
6 OUT R1,4
DONE:
7 HALT
// Input two numbers and output the higher
Dans ce 2eme exemple, si R1 est supérieur à R0 (test à la ligne 2), alors le programme effectue un branchement conditionnel à la ligne 3 (BGT est le branchement pour Greater Than).
Si R1 > R0, alors le programme passe directement de la ligne 3… à celle dont l’etiquette est HIGHER, donc à la ligne 6.
Sinon il passe à la ligne 4 (OUT R0,4), ce qui est le cours naturel de lecture du programme, ligne après ligne. Le branchement à la ligne suivante, B DONE le renvoie à la ligne d’etiquette DONE. Ce qui evite d’executer OUT R1,4 qui est réservé au branchement HIGHER.
Remarque: on peut choisir n’importe quelle nom pour l’etiquette que l’on met dans le programme: HIGHER, TEST, DONE, … peu importe.
question a: qu’est ce qui est affiché si l’on saisit la valeur 18 pour R0 et 9 pour R1? Puis 10 pour R0 et 20 pour R1?
question b: à quoi sert la ligne 6 B DONE? Que se passerait-il si cette ligne n’y était pas, et que l’on saisit la valeur 18 pour R0 et 9 pour R1?
question c: Ecrire dans votre cahier le script correspondant en python.
Exemple 5: boucle infinie
Le programme s’execute de la manière suivante: ligne 0 (affectation de la valeur 16 au registre R0), puis ligne 1 (on definit une etiquette boucle), puis ligne 2 (addition R0+1), puis ligne 3, ligne 4, …
MOV R0, #16
boucle:
ADD R0, R0, #1
OUT R0,4
B boucle
HALT
question a: Pourquoi le programme s’appelle-t-il boucle infinie?
Le test conditionnel if R0 > 20: break, qui va permettre de sortir de la boucle va s’écrire en assembleur:
CMP R0, #20
BGT break
L’étiquette break devra alors être placée après celle B boucle afin de pouvoir poursuivre le programme.
question b: Ré-écrire le script précédent afin de sortir de la boucle lorsque R0 stocke une valeur supérieure à 20.
Programmer avec des boucles
Prog 1: Calculer 1+2+3…+n où n est entré au clavier:
Compléter le programme en assembleur ci-dessous pour résoudre le problème puis essayer avec n = 3 en mode pas à pas.
Exécuter avec RUN en vitesse maximale pour n = 10
INP R0,2
MOV R1,#0 // compteur de boucle
MOV R2,#0 // somme
boucle:
ADD ...........
ADD ...........
CMP ...........
.... boucle
OUT R2,4
HALT
questions prog 1.
Estimer le nombre d’opérations significatives effectuées pour n = 10.
Estimer le nombre d’opérations significatives qui seraient réalisées pour n = 100.
Ecrire dans votre cahier le script correspondant en python.
Prog 2: boucle while
Ecrire le programme assembleur équivalent:
x=0whilex<3:x=x+1print(x)
A la fin du programme, la variable x doit être égale à 3.
Astuce: Le while est suivi d’une condition d’execution (x<3). Ici, en assembleur, on utilise plutôt une condition d’arrêt.
Ainsi, l’instruction python while x<3 sera écrite à l’aide de plusieurs lignes en assembleur:
CMP R0,#3
BEQ sortieboucle
...
B revenirwhile
questions prog 2.
Quelle est la condition d’arrêt correspondante?
Ecrire dans votre cahier le script complet en assembleur.
Prog 3: Pair/Impair
Ecrire en assembleur un programme utilisant des fonctions parmi LSL, LSR, B et BNE qui affiche 1 si le nombre est pair , 0 sinon. (BNE: Branchement si Not Equal).
n=int(input('entrer un nombre'))x=n//2x=n*2ifn==x:print(1)else:print(0)
question prog 3.
Ecrire dans votre cahier le script complet en assembleur.
operations sur les tables, représentation en python
Sous-sections de Donnees
Denombrer
Données, machines, algorithmes, langages
Dénombrer: du comptage au calcul mécanique
1. Ecriture des nombres: (Bordas p9)
mots clés: le statut de nombre, base 10, 2, 16, Leibniz et le binaire
Systeme de numération égyptien et gréco-romain (source:Bordas NSI)
Voir la page dédiée dans la partie SNT sur la numération au cours des ages: Lien
2. Les abaques et le boulier
Comment additionne t-on deux nombres avec un abaque?
Un abaque est le nom donné à tout instrument mécanique plan facilitant le calcul.
Au départ, une opération aussi simple que l’addition demande de la mémoire, d’utiliser les doigts de la main, ou des artefacs (petits cailloux ou des petits jetons en argile) : jusqu’à 3300 ans avant JC, voire plus tard selon les civilisations.
Puis les abaques ont permi d’exploiter la numération de position en base 10 en séparant les unités des dizaines, centaines, et plus, avec des jetons en colonnes.
La colonne la plus à droite étant celle des unités, celle à sa gauche, les dizaines, …
Reconstitution d'un abaque romain
La méthode est expliquée ici avec un container de billes, mais elle peut être adaptée facilement à l’usage du boulier…
On dispose les billes dans chaque colonne (centaine à gauche, puis dizaine et unité à gauche). Les nombres à additionner sont écrits sur 2 rangées, l’une sous l’autre.
104 + 17 - debut
On deplace les billes dans l’une des rangées
104 + 17 - etape 2
On rassemble les billes par 10 lorsqu’il y a un depassement dans l’une des colonnes, et on les remplace par une retenue dans la colonne plus à gauche.
104 + 17 - etape 3
On peut alors exprimer le résultat: 104 + 17 = 121
104 + 17 - resultat
Exercice:
Représenter les étapes de la soustraction de 15 à 103 à l’aide de ce même abaque.
Le boulier
Le boulier est un dispositif mécanique d’aide au calcul. Il est lié au système de numération décimale.
Youtube: Les bouliers - Micmaths
Exercice:
Représenter les étapes de la multiplication de 6 par 4 avec un boulier à 10 unités.
Représenter les étapes de la division de 32 par 8 avec ce même boulier.
Pourquoi l’auteur de la video avance t-il que le disque mécanique est une amélioration importante par rapport aux colonnes droites de billes?
Quel est le problème qui survient lorsque l’on compte avec le disque numéroté?
Ce manuscrit exceptionnel, écrit par Leibniz à 33 ans mais non publié, fait le lien entre deux de ses travaux majeurs, paraissant a priori indépendants : son idée du calcul binaire et son idée de machine à calculer décimale.
Ce manuscrit apparaît à ce jour comme la plus ancienne évocation d’un calculateur binaire.
Pour la numération additive, la lecture d’un nombre se fait en additionnant les valeurs de chacun des chiffres-caractères.
Exemple: la numération egyptienne
Numération de position
La numération de position permet d’écrire un nombre avec les mêmes symboles pour les rangs 0, 1, 2, etc… Le rang zero étant le plus à droite. Le poids d’un chiffre dépend de son rang:
$$Poids = Base^{rang}$$
La numération de position implique d’utiliser un symbole pour le zero.
Base
Une base est un nombre qui permet de décomposer un nombre entier dans une numération de position:
Base 10:
division euclidienne de 4 par 2
Pour convertir un nombre N décimal dans la base 2, on réalise la division par 2 de N puis des quotients de ses divisions, jusqu’à ce que le quotient arrive à 0.
Le resultat de la conversion en base 2 est la série de valeur obtenues pour les restes. Le dernier reste obtenu est celui de poids le plus fort:
conversion: 4
Exemples et visuels
Visuels:
principe de gestion mecanique de la retenue
Youtube: How mechanical counters work, gears
Overflow avec un compteur mécanique
Youtube: How mechanical counters work, overflow
Mémoires
Les différents supports de stokage utilisés pour les ordinateurs modernes sont présentés [ici (wikipedia, mémoires informatiques)(https://fr.wikipedia.org/wiki/M%C3%A9moire_(informatique)#Mat%C3%A9riel_informatique)
Le codage binaire (2 états) se fait à l’aide:
d’une piste pouvant avoir 2 polarités magnétiques (disque dur, disquette)
un creux ou une bosse sur un support (DVD, CD-ROM)
materiaux reflechissant ou non reflechissant (CD-ROM à graver)
condensateur chargé ou déchargé (mémoire RAM, registres)
Les techniques de stockage mécaniques, par exemple par rubans perforés ont été largement utilisés dès le début de l’informatique, puis abandonnés au profit de supports plus pratiques et plus rapides
entiers naturels, relatifs et decimaux
Entiers naturels
Un entier naturel (positif ou nul) se code en base 2 : chaque bit représente une puissance de 2, exactement comme chaque chiffre décimal représente une puissance de 10 en base 10.
Avec $n$ bits, on peut coder $2^n$ valeurs différentes, comprises entre $0$ et $2^n - 1$ (car il faut compter la valeur 0).
nombre de bits ($n$)
nombre de valeurs codables ($2^n$)
intervalle des entiers représentables
4
16
[0 ; 15]
8
256
[0 ; 255]
16
65 536
[0 ; 65 535]
32
4 294 967 296
[0 ; 4 294 967 295]
Plus on dispose de bits, plus l’intervalle des valeurs représentables est grand, mais il reste toujours fini : il faut choisir à l’avance le nombre de bits utilisés pour coder un entier.
Dépassement de capacité (overflow)
Si le résultat d’un calcul dépasse la plus grande valeur codable sur le nombre de bits alloué, on parle de dépassement de capacité (ou overflow). La retenue supplémentaire ne peut pas être stockée : elle est perdue, et le résultat obtenu est alors complètement faux.
Exemple: sur 8 bits, 1111 1111 (soit 255) additionné à 0000 0001 (soit 1) devrait donner 256. Mais 256 nécessite 9 bits pour être codé : le 9ᵉ bit est perdu et il ne reste que 0000 0000, soit… 0 !
C’est ce type d’erreur qui est à l’origine de la destruction de la fusée Ariane 5, 37 secondes après son décollage en 1996 : une valeur de vitesse, trop grande pour le nombre de bits alloué à son codage, a provoqué un dépassement de capacité et un plantage du logiciel de guidage (ce bug, plus précisément, concerne la conversion d’un nombre à virgule flottante, notion que nous verrons plus loin dans ce cours).
Short YouTube de L'aventure Ariane 5
$370 Million Software Bug
Entiers relatifs
nombres signés
Les entiers signés sont positifs, negatifs ou nuls. Comme il n’est pas possible d’écrire, comme nous le faisons normalement, un nombre négatif avec un signe (-) devant, il va falloir utiliser une nouvelle convention.
La première idée est de reproduire le signe en utilisant le bit de poids fort du nombre pour le représenter. Les n – 1 bits restants donnent la valeur absolue binaire du nombre.
Problèmes:
2 représentations pour le zero
arithmetique plus difficile: on ne peut pas utiliser le même algorithme que pour l’addtion de 2 nombres positifs.
Représentation en complément à 2
C’est la représentation standard sur les ordinateurs pour exprimer les nombres entiers négatifs. Quand on parle de représentation signée ou d’entiers signés, ces derniers sont toujours exprimés à l’aide de la représentation en complément à 2.
Définition
Sur n bits, on exprime les nombres de l’intervalle $[–2^{(n-1)}; 2^{(n – 1)}– 1]$ selon les 2 règles suivantes:
Un nombre positif est représenté de façon standard par son écriture binaire.
un nombre négatif est représenté en ajoutant 1 à son complément à 1 (obtenu en inversant tous les bits) et en laissant tomber une éventuelle retenue finale.
il est important d’indiquer sur combien de bits doit s’écrire le nombre car on ne rajoute pas des zéros en tête mais 1…
Intérêt : on n’a plus à se préoccuper du signe des nombres avant d’effectuer l’opération.
Exemple:
Soit l’entier signé - 127 (1000 0001) que l’on additionne à 127 (0111 1111):
Représentation des nombres décimaux
nombres fractionnaires
Un nombre avec virgule, exprimé en base décimale peut être représenté comme une somme de puissances de 10:
écriture d'un nombre à virgule en base 10
Les puissances de 10 positives pour la partie entière (à gauche de la virgule)
les puissances de 10 negatives pour la partie après la virgule
En base 2, le nombre peut aussi s’écrire avec une virgule, et être lu comme une somme en puissance de 2:
écriture du même nombre en base 2
Les puissances de 2 positives pour la partie entière (à gauche de la virgule)
les puissances de 2 negatives pour la partie après la virgule
Pour représenter des nombres avec une partie fractionnaire, décomposer la partie fractionnaire en puissances inverses de 2:
$2^{-1}$
$2^{-2}$
$2^{-3}$
$2^{-4}$
$2^{-5}$
$2^{-6}$
$2^{-7}$
$2^{-8}$
1/2
1/4
1/8
1/16
1/32
1/64
1/128
1/256
0,5
0,25
0,125
0,0625
0,03125
0,015625
0,0078125
0,00390625
Lorsque l’on représente la partie décimale de 0.375, on a une valeur exacte que l’on peut coder sur 1 seul octet:
conversion binaire de la partie décimale .0375
Le problème est que la représentation d’un nombre peut être finie dans une base donnée, et être infini dans une autre:
conversion binaire de la partie décimale .1
Si on n’utilise que 8 bits pour la partie décimale de 0.1, la valeur numérisée vaut alors:
Il existe une méthode systématique pour déterminer les bits de la partie fractionnaire. Voir le Bordas p18, §5.
codage en virgule fixe
Une première idée pourrait être d’utiliser 2 octets:
1 octet pour la partie entière. Si le nombre est signé, cela veut dire que le nombre est compris, pour sa partie entière entre -128 et 127.
1 octet pour la partie décimale. Cette partie est alors codée sur 256 valeurs, selon la méthode vue plus haut).
Il y a alors 2 problèmes avec cette représentation:
Problème 1: La partie fractionnaire va manquer de précision. Il n’y aura pas assez de chiffres significatifs lors de l’approximation. L’écart avec la valeur vraie du réel peut être trop important si on veut une précision raisonnable
Problème 2: Certains nombres ont une représentation avec un nombre fini de chiffres après la virgule dans la base 10, mais infinie dans la base 2. (voir la cas du 0.1 vu plus haut, qui est approximé à 0.09765625).
Ces approximations sont alors la source d’erreurs de calcul en python:
somme de 0.1 + 0.2 en python
codage en virgule flottante: norme IEE754
Principe
Pour un ordinateur, TOUT est discrêt: cela signifie que les nombres réels seront approchés par des nombres dits à virgule flottante.
Ces nombres avec une partie décimale sont représentés sur ordinateur selon la norme IEEE 754.
Ce codage revient à représenter le nombre sous la forme:
$$+/-1,M.2^E$$
Cette forme rappelle ainsi l’écriture en notation scientifique.
M s’appelle la mantisse du nombre et E l’exposant. Comme la mantisse commence toujours par une partie entière égale à 1, on ne l’écrit pas et on n’exprime que la partie fractionnaire, M
Selon la précision, dite simple ou double, le nombre M est constitué de 23 bits ou bien de 52 bits.
precision
bit de signe
E
M
simple
1
8
23
double
1
11
52
Selon cette norme IEEE 754, en 32 bits (simple precision):
Le premier bit est celui du signe
les 8 bits suivants sont les bits de l’exposant E, exprimé en nombre relatif. Ce qui permet de coder l’exposant avec des valeurs comprises dans l’intervalle [-127; 128]
les bits restants sont ceux de M
Cette méthode est-elle précise?
En raison du nombre limité de bits de la représentation, les calculs en virgule flottante ne peuvent pas atteindre une précision infinie.
On a un bit de signe égal à 0, un exposant égal à 8 + 127 et les premiers bits de la pseudo-mantisse qui exprime 0,953125.
Pour représenter des constantes physiques:
Vers l’infiniment grand, le nombre d’Avogadro vaut $6,0221.10^{23}$. Celui-ci, exprimé avec 5 chiffres significatifs, suffit à la plupart des calculs scientifiques.
Vers l’infiniment petit, la masse du proton est $9,1094.10^{-31}$. Avec 5 chiffres significatifs.
Avec la norme IEE754 sur 32 bits, les exposants de 2 varient de -126 à 127. Ce qui correspond à peu près à $\pm 10^{38}$. Et le nombre de chiffres significatifs est sur 23 bits, ce qui signifie que la partie décimale est représentée avec 7 chiffres significatifs.
La multiplication et division par 2 d’un nombre binaire
La multiplication par 10 d’un nombre exprimé en base 10 va décaler la virgule vers la droite. Par exemple:
$$8,314 \times 10 = 83,14$$
De la même manière, pour un nombre binaire:
la multiplication par 2 décale sa virgule vers la droite
la division par 2 décale sa virgule vers la gauche
Exemple avec la multiplication binaire: (nombres exprimés en binaire, sans faire référence à la norme IEE754)
$$1010.101 + 1010.101 = 10101.01$$
Conclusion
Les règles de calcul en binaire seront les mêmes, que les nombres binaires soient des entiers naturels, relatifs, fractionnaires.
Un même mot-binaire peut représenter un entier naturel, relatif, fractionnaire. Il faut donc bien distinguer un nombre de sa représentation.
Exercices sur les nombres fractionnaires
Norme IEEE 754
Le nombre suivant est écrit dans la norme IEEE 754:
$0~10000111~11110100000000000000000$$
Repérer dans ce nombre:
le bit de signe
les bits correspondant à l’exposant
les bits de la mantisse
Mantisse
Pour les questions suivantes, utiliser le tableau des puissances négatives de 2:
$2^{-1}$
$2^{-2}$
$2^{-3}$
$2^{-4}$
$2^{-5}$
$2^{-6}$
$2^{-7}$
$2^{-8}$
1/2
1/4
1/8
1/16
1/32
1/64
1/128
1/256
0,5
0,25
0,125
0,0625
0,03125
0,015625
0,0078125
0,00390625
question a: On donne la partie fractionnaire d’un nombre binaire (la mantisse):
$$1110~0000$$
Donner la valeur correspondante en base décimale.
question b: La partie fractionnaire suivante (mantisse) est une approximation de 0,1:
$$0001~1001$$
Vérifiez le par un calcul
question c: Une meilleure approximation de 0,1 est donnée par le nombre fractionnaire suivant (mantisse):
$$0001~1001~1001~1001~1001...$$
Que constatez-vous?
question d: Lorsque l’on réalise l’addition binaire suivante, en python, on obtient un résultat approché et incorrect. Pourquoi?
>>>0.1+0.20.30000000000000004
Multiplication et division par 2
On utilise une représentation binaire avec une virgule flottante. A gauche de la virgule, le nombre binaire se lit d’une manière classique, comme pour les entiers naturels. A droite de la virgule, il s’agit de la partie fractionnaire en puissance négatives de 2.
question a: Quel est la valeur en base 10 de $0.1$(binaire). Calculer $0.1$(binaire) multiplié par 2.
question b: Quelle est la valeur binaire de $1101.1100$(binaire) divisé par 2?
Norme IEEE 754 à 5 bits
Pour l’exercice nous inventons une nouvelle norme: la IEEE 754 à 5 bits.
Avec 5 bits, nous pouvons coder 25 nombres flottants. La precision est alors de 2 chiffres significatifs (taille en bits de la mantisse). Le format binaire est ainsi:
Voici la liste des 16 positifs :
Supposons que l’exposant E se calcule d’après e selon la règle suivante:
$$E = e - 1$$
Question: écrire les nombres binaires correspondants à ces 16 positifs.
Rappelez vous que le nombre s'écrit sous la forme:
$$+/-1,M.2^E$$
Un texte est une chaine de caractères et de symboles (dont l’espace, virgule…). La représentation du texte dans l’ordinateur suit ce même schéma : c’est le rangement à des emplacements consécutifs de la mémoire des représentations des caractères un à un. Il existe plusieurs normes d’encodage des caractères.
Code ASCII
Une des première normes a été l’ASCII (American Standard Code for Information Interchange), qui est apparue aux états unis, à l’époque où les ordinateurs n’étaient pas connectés en reseau.
table ascii pour les nombres 0-127
Le problème de l’encodage ASCII est qu’il ne permet pas de représenter assez de caractères pour les besoins des différentes langues.
Une autre norme, encore utilisée est l’ASCII étendu, dont les caractères sont encodés sur 8 bits.
table ascii-Latin1 pour les nombres 128-255
Il existe plusieurs tables ascii-étendu, celle présentée ici est celle Latin1, utile pour les caractères du français et autres langues d’europes de l’ouest.
En ASCII étendu: 1 octet par caractère. On peut évaluer la taille d’un fichier: C’est le nombre N caractères, exprimé en octets.
informations sur un fichier textuel (Word)
La principale limitation des jeux de caractères codés sur un octet, comme l’ascii-Latin1, est la nécessité d’utiliser plusieurs jeux de caractères codés pour couvrir plusieurs alphabets.
Attention à la compatibilité avec les documents web:
Les jeux de caractères en un seul octet ne sont pas compatibles avec la norme actuelle, l’utf-8 (voir plus loin).
Dans un document HTML, on pourra tout de même afficher correctement ces caractères, mais il faudra:
soit utiliser une entité HTML, c’est à dire une combinaison de symboles connus par le navigateur comme par exemple: é pour la lettre é
soit choisir un encodage UNICODE ou utf-8
Les normes suivantes vont proposer des formats qui vont:
être compatibles avec l’ASCII 7 bits, pour faire évoluer le web tout en restant retro-compatible avec la plus ancienne et la plus internationale des normes
permettre l’encodage de TOUS les caractères existants ou à venir
Unicode
Le répertoire Unicode se décline en utf-8, utf-16 et utf-32, qui sont de largeur variable ou fixe (pour utf32)
Le code UNICODE permet de représenter tous les caractères spécifiques aux différentes langues.
Cette gigantesque table est divisée en 17 plans (de 0 à 16) de deux octets chacun, soit 65 536 points de code par plan (65 536 x 17 = 1 114 112). Ces plans permettent de désigner facilement des groupes de caractères. Le premier plan, appelé Basic Multinlingual Plane (BMP), ou Plan Multinlingue de Base, regroupe les 65k caractères les plus courants. Les plans 1 à 16 sont appelés plans supplémentaires.
L’inconvenient des encodages à largeur fixe (utf-32) est qu’ils vont générer des fichiers de poids important (poids compté en kilo octets). Bien plus lourd que l’encodage ASCII. Alors que bien souvent, la plupart des caractères utilisés pour un document texte sont ceux de l’alphabet ASCII, avec quelques caractères spéciaux.
Code à largeur variable utf-8 et utf-16
Cet encodage utilise l’ASCII pour les caractères dont le point de code est inférieur ou égal à 127.
Chaque caractère dont le point de code est supérieur à 127 (0x7F) (caractère non ASCII) se code sur 2 à 4 octets.
La longueur du nombre binaire est alors variable. Un caractère peut nécessiter 8 (ascii), 16 bits, ou plus (jusqu’à 32). Une information dans le code numérique va préciser cette longueur (correspond à un caractère spécial comme le Ã). Cela va permettre d’afficher tous les caractères. Cela génère un fichier dont le poids sera inférieur à l’utf-32.
Pour le système d’exploitation Windows, l’encodage par defaut est l’utf-16. MacOs utilise un encodage utf-8.
La séquence binaire contient alors un premier code qui indique la longueur de bits à venir. C’est comparable au système utilisé pour les masques de sous-reseau.
0bbbbbbb 1 octet codant 1 à 7 bits
110bbbbb 10bbbbbb 2 octets codant 8 à 11 bits
Ainsi, le caractère é est représenté en utf-8 par la séquence binaire 11000011 10101001. Parmi les chiffres binaires, seuls ceux en gras sont codants pour la valeur numérique associée à ce caractère. Il s’agit donc de 000 1110 1001. C’est la valeur E9 en hexadécimal. (233 en décimal).
Pour une image en couleur: À chaque pixel on associe 3 couleurs, le rouge, le vert et le bleu. On parle du canal rouge, du canal vert et du canal bleu d’un pixel (système RVB ou RGB en anglais).
credit - photograpix.fr/blog
La valeur de l’intensité lumineuse associée à chaque canal de chaque pixel d’une image est comprise entre 0 et 255 (256 valeurs possibles). On codera donc un pixel à l’aide d’un triplet de valeur (par exemple (247,56,98) en code décimal, ou son équivalent en hexadecimal : (f7,38,62)
Question a: Reproduire et compléter l’image du cercle chromatique, représentant la synthèse additive des couleurs. (placer les termes: Rouge, Vert, Bleu, magenta, cyan, jaune).
Pour la suite, vous avez le choix entre 2 options:
Question b: à l’aide du logiciel :
Quelle est la couleur donnée par le triplet de valeurs: (247,56,98)?
Question c: Combien de couleurs différentes est-il possible d’obtenir avec ce système RVB ? (combinaison de 3 couleurs, codées chacune sur 256 valeurs,…)
Question d: Pour chacune des couleurs du tableau, indiquer le code couleur RGB décimal correspondant (voir ci-dessous).
Question e: Précisez la particularité des teintes grises au niveau des valeurs RVB/RGB
code couleur RGB
codage d'une image
Coder une image
Une image: un tableau de pixels
image pixelisée monochrome
Comment représenter l’image de ce symbole de manière numérique? Compléter la grille de droite avec les valeurs 0 ou 1.
L’objet mathematique correspondant est une matrice. C’est un tableau constitué de lignes et colonnes. Le caractère a sera représenté par la matrice M:
M=[[1,0,0,0,1],[1,1,1,1,0],[..],[..],[..],[..]]
M est une liste de lignes, où chaque ligne est aussi une liste.
Construire une image numérique
On utilise des boucles simples ou imbriquées, constituées d’une seule ou plusieurs instructions pour peindre les pixels (voir activité sur le site Algorea):
pixels sur une ligne: boucle simple
faire 6 fois:
peindre en rouge
faire 6 fois:
peindre en bleu
tableau de pixels. boucles imbriquées
faire 12 fois:
faire 6 fois:
peindre bleu
peindre rouge
Les plus petits détails de l’image sont ses pixels : des petits carrés remplis chacun avec une seule couleur.
Coder les pixels de l’image revient à coder les couleurs de ses pixels.
Les valeurs des couleurs des pixels sont alors mises les unes à la suite des autres, et constituent ainsi le fichier image en s’ajoutant aux métadonnées.
P1
6 5
0 1 1 1 0 1
0 0 0 0 1 1
...
Grâce aux métadonnées du fichier, les informations de format (P1, P2, …) et de dimension (6 * 5), l’ordinateur va traiter cette suite de chiffres selon une matrice de valeurs:
import des données du fichier dans un programme python. Codage des couleurs en 24 bits rgb
Chaque information va coder la couleur d’un pixel (un petit carré de couleur uniforme). Une fois agrandie, l’affichage ne pourra pas proposer plus d’informations que celles contenues dans le fichier source. C’est pour cette raison que l’image apparait parfois pixelisée.
image pixelisée couleur
Le poids de cette image : pour 100 pixels sur 100 pixels (10 000 px)
Saurez-vous deviner le codage des couleurs sur cette image?
certains logiciels de design proposent de faire des essais de coloration. Ici, données en hex
Caractéristiques des images
Luminosité d’une image
La luminosité d’une image représente la clarté de l’image.
Pour un pixel donné, on peut établir une mesure de la luminosité de la manière suivante :
Soient R, V et B les valeurs des intensités de chaque canal coloré. La luminosité L est égale à :
$$L = R+V+B$$
Pour calculer la luminosité moyenne d’une image, voici l’algorithme:
s = 0
pour chaque ligne:
pour chaque colonne:
p <- couleur du pixel
s = s + (p[0] + p[1] + p[2])/3
luminosite <- s / (ligne*colonne)
Pour chaque pixel, on fait la moyenne de ses 3 couleurs primaires.
On ajoute la valeur à l’accumulateur s. Puis on fait la moyenne des valeurs de s en divisant par le nombre de pixels (ligne*colonne).
Contraste
Les deux images présentées dans le paragraphe précédent, sur la luminosité, sont trop peu contrastées pour en apprécier le contenu.
En effet, l’amplitude de luminosité entre les pixels clairs et les pixels foncés est trop petite.
En d’autres termes, les tons sombres et les tons clairs de l’image ont des luminosités qui ont des valeurs trop proches.
Le contraste mesure la différence de luminosité entre les tons clairs et les tons sombre.
Exemple :
images faible contraste
Soient les fonctions recherche_du_max et recherche_du_min qui retournent la valeur du max ou du min dans une liste python simple.
img est un tableau de valeurs des couleurs en niveau de gris des pixels. Par exemple:
Le programme va parcourir chaque ligne, c’est à dire chaque sous-liste de img.
Si la fonction max_ligne retourne une valeur supérieure à max, c’est qu’une valeur plus grande d’intensité a été trouvée dans cette ligne. On remet à jour la valeur max de l’image avec max = max_ligne, et on passe à la ligne suivante.
(même principe pour min_ligne)
max = 0
min = 255
pour chaque ligne de img:
max_ligne = recherche_du_max(ligne)
min_ligne = recherche_du_min(ligne)
si max_ligne > max: max = max_ligne
si min_ligne < min: min = min_ligne
Qualité des images
La définition D d’une image est définie par un nombre de pixels selon la longueur et la largeur de l’image numérique. C’est une caractéristique propre de l’image.
On l’exprime le plus souvent en donnant les dimensions du plan de pixels, par exemple, une image de définition :
$$1900 \times 1700~pixels$$
La résolution R d’une image numérique correspond à sa densité en points (pixels). On mesure la densité de pixels sur l’écran en pixels par pouce (ppi) et la densité de points sur l’image imprimée en points par pouce (dpi). Ce n’est pas une caractéristique de l’image elle-même, mais de sa restitution par un écran (ou imprimé).
Selon le cas, on calculera la résolution selon l’un des côtés de l’image. Ou bien selon la diagonale de l’iamge.
La résolution peut s’exprimer en pixels par pouce. On peut en déduire la résolution en pixels par cm à l’aide de la relation suivante
entre la Définition D, la Résolution R, et le nombre de cm par pouces (2,54).
En effet : 1 pouce vaut 2,54 cm. Un petit calcul montre que R = 72 ppi correspond à 28,3 pixels pour 1 cm.
Exemple : Soit une image de définition 800x533 que l’on imprime sur du papier photo de taille 15x10 (en cm), calculez la résolution de cette image en ppp.
Réponse : On prendra :
Définition : D = 800px et Longueur : L = 15 cm. On cherche R : resolution
Agrandissement et perte de qualité: lorsque le nombre de points codés dans l’image est inférieur au nombre de pixels de l’écran, il n’y a pas assez de points. L’agrandissement va déteriorer l’image, car un même point va être placé sur plusieurs pixels côte à côte. C’est ce que l’on appelle la pixelisation de l’image.
agrandissement jusqu'à pixelisation
La selection d’une partie des points de l’image montre qu’il n’y a plus assez de points avec le zoom x12. On peut afficher une image à partir de cet agrandisement, mais il y a pixelisation. (voir la partie sur la transformation d’une image)
Transformation des images
Poids d’une image avec/sans compression
Image matricielle sans compression
En format brut.
A partir de ce qui a été vu plus haut, le poids d’une image non compressée de définition D et de profondeur de couleur C a un poids P :
$$P = D \times C$$
Exemple : D = 1900 pixels * 1700 pixels et C = 3 octets
En réalité, les images sont compressées. Ce qui permet d’avoir un poids moindre pour leur stockage, leur transfert…
Image matricielle avec compression
La compression d’une image c’est la réduction de la quantité d’informations nécessaires pour décrire l’image. Les idées générales sont :
De rassembler plusieurs pixels de même couleur, et établir une couleur moyenne des pixels sur une zone donnée.
supprimer des informations : par exemple en diminuant le nombre de couleurs possibles. On fait une réduction de l’espace des couleurs à celles qui sont les plus fréquentes dans l’image.
Le format PNG est un format d’image bitmap qui utilise la compression sans perte. Le facteur de compression n’est alors pas très élevé. Les données y sont réorganisées pour tenir moins de place. La compression utilise l’algorithme Deflate, basé sur le code de Huffman.
Rappelez vous que le fichier image est constitué de caractères (base 64). C’est donc les occurences de ces caractères dans le fichier qui permet la compression avec l’agorithme Deflate.
exemple de code de Huffman pour la compression d'un texte
Le format jpg est un format compressé avec pertes. L’idée est de supprimer la différence de valeur des couleurs pour des pixels contigûs, aux couleurs proches.
La compression réduit la taille du fichier, mais dégrade la qualité de l’image.
On parcourt ensuite chaque valeur de pixel de l’image source, on effectue un traitement sur ces valeurs, et on place chacune dans la matrice de l’image cible.
image issue du site de frederic-junier.gitlab.io
Puis on construit l’image cible à partir de sa matrice.
Transformation de la taille d’une image
Certains logiciels permettent de reduire ou agrandir la taille d’une image (resize). Cela modifie le nombre de pixels. Cette transformation se fait en conservant les proportions de l’image (homothétie).
La reduction consiste à choisir certains points de l’image d’origine pour les placer dans celle reduite.
Un agrandissement simple peut se faire en reportant la valeur d’un point sur un carré de points de l’image agrandie:
L’agrandissement peut aussi se faire en faisant une interpolation des valeurs des points (on invente les couleurs manquantes par un calcul de moyenne)
Interpoler: introduire dans une série de valeurs, de nouvelles valeurs intermédiaires.
Merci à zonensi.fr pour le travail sur cette partie du cours.
Lire/écrire dans un fichier
Les algorithmes de compression, d’agrandissement ou de reduction d’image agissent sur D (definition) ou sur C (profondeur de couleur) définis plus haut. Voyons ici la méthode pour lire et écrire dans un fichier image d’extension .ppm. Cela peut se faire à l’aide des fonctions natives de Python. Une autre option est d’utiliser la librairie PIL, comme vu en TP.
Soit le fichier image_source.ppm, dont le contenu est donné ci-dessous (4 premiers pixels)
Ce format en listes pour les valeurs des couleurs de pixels est utile pour appliquer un traitement.
Pour recomposer la chaine de caractère à partir de la liste, il faut faire l’opération inverse de line.split(), c’est à dire:
> ' '.join(['87', '87', '87'])
'87 87 87'
On peut rediriger les valeurs vers un nouveau fichier:
f1=open('image_source.ppm','r')f2=open('image_copie.ppm','w')largeur=1000hauteur=801f.write('P3'+'\n')f.write(str(largeur)+' '+str(hauteur)+'\n')f.write('255'+'\n')forlineinf1.readlines()[3:]:L=line.split()# ici: traitement sur les valeurs du pixelpixel=' '.join(L)f2.write(pixel+'\n')
Exercices
Recherche du min/max
Pour parcourir un tableau T à 2 dimensions, il faut 2 boucles imbriquées, la 1ere pour parcourir les lignes, et la 2e pour les colonnes.
Cela donne souvent le script suivant:
script A:
foriinrange(len(T)):# i est le numero de ligneforjinrange(len(T[0])):# toutes les lignes ont la meme longueur que T[0]# j est le numero de colonne...traitementsurT[i][j]
script B:
forlineinT:foreleminline:...traitementsurelem
Lequel de ces scripts realise un parcours par indice? Lequel realise un parcours par élément.
Utiliser l’un de ces scripts pour écrire une fonction min_max, qui détermine la valeur minimale et la valeur maximale parmi les données de la matrice.
Ecrire une fonction moyenne qui retourne la moyenne des valeurs d’une matrice.
Compréhension de liste
Le script suivant construit une matrice M de zeros:
n=4m=6M=# a completer (1)foriinrange(n):forjinrange(m):line.append(0)# a completer (2)
Compléter le script
Quelle est la dimension de cette matrice? Et quelles seraient les dimension de l’image correspondante (largeur/hauteur)?
Simplifier le script au niveau des lignes 5 et 6, en utilisant l’instruction [0] * n, qui est équivalent, ici, à [0,0,0,0].
Ré-ecrire ce même script, en utilisant la compréhension de liste.
Créer une image à partir d’instructions
drapeau suisse
Ecrire le script qui permet de construire la matrice de ce drapeau suisse, en noir et blanc. La dimension sera de 700*500 pixels
Ecrire le script qui construit la matrice du drapeau, mais cette fois, avec la couleur de fond rouge. Chaque élément de la matrice sera un tuple (R,V,B)
Traitement d’une image sans modifier sa dimension
On souhaite transformer une image source en couleur, en une image cible en niveaux de gris. On utilise pour cela la formule de calcul de la Luminence: *(r,g,b sont les intensités des couleurs primaires 0..255)
$$L = 0.299\times r + 0.587\times g + 0.114\times b$$
La valeur calculée pour L sera placée comme niveau de gris dans la matrice cible.
Ecrire le script de la fonction luminence, qui calcule la valeur de L à partir d’un tuple (r,g,b)
Placer dans la fonction un test d’assertion sur les valeurs permises pour r,g,b. Ce test, basé sur les données d’entrée, est appelé test de précondition
Ecrire une fonction matrice_rgb_to_gris qui créé une matrice de niveaux de gris (valeurs de luminence) à partir d’une matrice couleur.
Agrandissement, reduction
On considère une image source de largeur L et de hauteur H et un entier $k > 0$ :
Un agrandissement de coefficient k de l’image source est une image cible de dimensions $(k\times L,k \times H)$ dont le pixel de coordonnées $(x, y)$ prend la valeur du pixel en $(x//k, y//k)$ dans l’image source.
image issue du site de frederic-junier.gitlab.io
On considère l’image 3*3 de matrice M = [[1,0,1],[0,1,0],[1,1,1]]. Quelle sera la dimension de l’image cible si le coefficient k est égal à 2?
Représenter la matrice M_cible avec ses valeurs calculées à partir de celles de M
La fonction changement_echelle prend 2 paramètres, M, la matrice $(L,H)$ de l’image source, et k, le coefficient. Cette fonction retourne une image calculée sur les valeurs de M, avec une dimension $(k\times L,k \times H)$. Ecrire le script de cette fonction.
Cette fonction, sert-elle aussi pour réaliser une reduction de la taille de l’image source? Donner un exemple.
Quel défaut aura une image agrandie selon cette méthode?
Quel sera le poids de l’image reduite d’un facteur k? Exprimer en fonction du poids P de l’image source.
Fiche d’exercices sur les images numeriques: version pdf
Représenter les 3 circuits ci-dessous avec l’editeur logic.ly
Exemples de circtuits créés à l'aide du simulateur logic.ly
Questions:
1.a. Les circuits permettent-il une interaction avec l’utilisateur?
1.b. Pour chaque circuit: Quels sont les composants utilisés?
1.c. Pour chacun des circuits: Expliquer le comportement du circuit, pourquoi la lampe s’allume (ou pas)?
Toute fonction logique peut se décomposer en fonctions NON, ET, OU. Les exemples suivants ont pour but de se familiariser avec ces combinaisons de portes logiques, et d’aboutir à la construction d’un ADDITIONNEUR à 2 bits.
Simulation d’une porte logique NON
Voici le schéma formel représentant la fonction NON, réalisée à l’aide d’une porte logique NAND (NON ET):
schéma formel
Vous allez adapter ce schéma pour réaliser sur le circuit suivant sur le simulateur:
realisation sur logic.ly
Les 2 entrées de la portes NAND sont reliées au même interrupteur. L’interrupteur fournit une tension au circuit, à 2 état (Allumé / Eteint).
Une lampe est aussi mise en entrée, sur l’interrupteur, afin de visualiser l’état d’entrée.
2.a. Représenter la table des états pour ce dispositif. S’agit-il de la même table que celle de l’opérateur NON?
E
S
0
1
La formule logique associée au schéma que vous avez réalisé est:
$$NOT(x) = NAND(x,x)$$
2.b. Commentez cette formule. Identifiez chacun des termes par rapport au circuit.
Simulation d’une porte logique ET
Voici le schéma formel représentant la fonction ET, réalisée à partir des portes logiques NOT et NAND:
schéma formel
Réalisez le circuit correspondant sur logic.ly
3.a. Représenter la table des états pour ce dispositif. S’agit-il de la même table que celle de l’opérateur ET?
E1
E2
S
0
1
0
1
La formule correspondant à cette association est:
$$AND(x,y) = NOT(NAND(x,y))$$
3.b. Commentez cette formule. Identifiez chacun des termes par rapport au circuit.
Porte logique OR
Sachant que:
$$NOT(OR(x,y)) = AND(NOT(x),NOT(y))$$
4.a. Construire et représenter le schéma électronique de $AND(NOT(x),NOT(y))$ à partir des portes AND et NOT.
4.b. Ce circuit est-il équivalent à $NOT(OR(x,y))$?
4.c. Conclure: Comment réaliser la fonction $OR(x,y)$ à partir des portes NOT et AND?
Additionneur 1 bit
Un additionneur 1 bit est vu comme deux fonctions booléennes s le chiffre des unités et cout la retenue de sortie dépendant de trois entrées:
3 entrées : deux bits a et b et une retenue d’entrée cin
2 sorties : Le bit de résultat s et une retenue de sortie cout
5.a. Créer un circuit add1 qui implémente l’additionneur 1 bit à partir du schéma ci-dessous
Additionneur 1 bit
5.b. Compléter la table de vérité des fonctions s et cout
a
b
cin
s
cout
0
0
0
1
1
0
1
1
0
0
0
1
1
0
1
1
5.c. Expliquez en quoi le circuit suivant est bien un additionneur de 2 bits, avec retenue.
Pour tracer un graphique, on peut avoir besoin d’une liste de valeurs [0, 1, 2, … 100] correspondant aux nombres de points relevés.
Cette liste peut être construite à l’aide d’une boucle bornée:
T=[]foriinrange(100):T.append(i)
On rappelle que range(100) créé une suite de valeurs que prendra le variant i, successivement, du premier au dernier.
Construire un tableau par compréhension
Cette méthode permet de construire une nouvelle liste “à la volée”, en parcourant les éléments d’une première liste.
T=[iforiinrange(100)]
Relever des valeurs
Lors d’une expérimentation, il est parfois utile de relever des valeurs mesurées au cours du temps.
Ces valeurs peuvent être stockées dans une liste, en utilisant la fonction append:
Souvent, les données issues d’une acquisition sont présentées sous forme d’une table.
Elles sont alors échangées avec le programme python grâce à un fichier de données en format csv. Il est alors possible de créer une liste de données par colonne: listes t, x, y, v
A partir de l’exemple précédent, on peut supposer que:
On peut alors ajouter une nouvelle colonne à ces données, c’est à dire une nouvelle liste.
Par exemple: à partir de la définition de l’energie cinétique:
$$Ec = \tfrac{1}{2}* m * v^2$$
Supposons que le mobile ait une masse m = 1 kg:
m=1Ec=[]forvitesseinv:Ec.append(0.5*m*v**2)
Remarque: de nombreux types de données peuvent être parcourus avec la syntaxe for x in t: par exemple des chaines de caractères. La différence avec range(100), c’est que ce dernier créé une liste itérable de valeurs ordonnées, de 0 à 99. On dit que la valeur x est itérable.
A vous de jouer:
quelle instruction permet de créer la même liste Ec, mais cette fois, par compréhension de liste.
télécharger le fichier
data_parabolique.csv
3. Ajouter une nouvelle liste calculée: $Ec = \tfrac{1}{2}* m * (vx^2+vz^2)$. Prendre m = 1. Compléter pour cela le programme:
m=1Ec=[]foriinrange(len(vx)):# vx et vz sont les 2 composantes de v# et ont la même dimension# v^2 est calculé à partir de# vx**2 + vz**2Ec.append(
Tracer le graphique Ec en fonction de x.
Aide: Script pour lire les données d’un fichier
fichier=open('data_parabolique.csv','r')# ouverture du fichier de donnéeslignes=fichier.readlines()# parcours du fichier par ligne lignes=lignes[1:]# eliminer la premiere ligne qui contient les labels x=[]t=[]forligneinlignes:t.append(float(ligne.split(';')[0]))x.append(float(ligne.split(';')[1]))
Parcours d’une liste
Soit la liste:
Temperature=[18.5,19.0,20.4,20.2,19.8]
Pour calculer sur les valeurs de liste, par exemple, la somme, ou la moyenne des valeurs, il faut parcourir ces valeurs:
s=0fortinTemperature:s=s+t
A vous de jouer: adapter ce script pour:
calculez la moyenne des valeurs de Temperature
Déterminez la valeur maximale de la liste
Utilisez votre script pour déterminer la valeur maximale de la liste z dans le fichier data_parabolique.csv
Recherche du nombre d’occurences dans une liste
On peut représenter une molécule par sa liste d’atomes.
Par exemple, la formule suivante peut être mise dans la liste:
Compter le nombre d’occurences signifie que l’on peut compter le nombre d’atomes identiques, comme par exemple le nombre de 'H' ou bien le nombre de 'C'.
n=0foratomeinmolecule:# ajouter une condition sur atome# si atome vaut 'C' (ou 'O' ou 'H')# alors n = n + 1
A vous de jouer. En vous inspirant du script précédent, vous allez écrire une fonctionoccurences qui prend une liste en paramètre, appelée molecule, ainsi qu’un caractère c, et compte le nombre d’occurences de c dans la liste molecule.
Matrices
Une liste peut elle-même contenir une liste. Une matrice est ainsi une liste de listes, dont les éléments sont tous de même type. La matrice forme une sorte de tableau rectangulaire, dont la premiere ligne correspond à la premiere liste, etc…
Pour parcourir les valeurs d’une matrice, on aura besoin de 2 boucles imbriquées:
# script pour afficher la matrice mm=[['a','b','c'],['d','e','f'],['g','h','i']]forligneinm:forcinligne:print(c,' ',end='')print('\n')# affiche # a b c# d e f# g h i
La première boucle bornée créé un itérable ligne qui vaut successivement:
['a','b','c']
['d','e','f']
['g','h','i']
La deuxième boucle (imbriquée), créé un itérable c à partir de chacune de ces sous-listes:
a
b
c
…
Les valeurs de m sont accessibles à partir de ses indices, comme pour une matrice:
m[0][0] vaut a
m[0][1] vaut b
m[0][2] vaut c
m[1][0] vaut d …
Exemple: traitement d’une image
une image numérique est constituée de pixels
Une image est représentée par un triplet de valeurs (un tuple) pour chacun de ses pixels, correspondant à l’intensité (Rouge, Vert, Bleu) (0-255) de ce pixel.
Soit l’image suivante, de dimension 3 pixels * 3 pixels:
Cette image est représentée par la matrice de valeurs (R,V,B):
Exercice: Ecrire un programme qui calcule la valeur moyenne sur toutes les valeurs RVB de cette matrice. Cela donnera l’intensité moyenne de cette image (sa luminosité).
Donnees en table
Données en table - introduction
Les tables structurent les données et permettent de réaliser facilement des opérations de recherche d’informations ou de calcul sur ces données.
Prenons l’exemple une agence de voyage, qui propose des activités sur mesure à ses clients.
les données sont organisées en 2 tables clients et sejours. Il y aura autant de tables que d’entités
Les tables clients et sejours ont un identifiant unique attribué lors de leur enregistrement.
CLIENTS
IDC
NOM
AGE
ACTIVITE
27
Ritta
19
Danse
19
Blaise
29
Cinema
11
Dede
59
Nature
18
Indie
58
Histoire
12
Kelly
30
Surf
17
Dupond
35
Surf
28
Nono
65
Plongée
SEJOURS
IDS
VILLE
ACTIVITE
1
Cayenne
Nature
10
Rio
Danse
11
Havane
Danse
12
Oahu
Surf
20
Durban
Plongée
65
Sydney
Surf
88
Rome
Art
90
Durban
Surf
L’agence de voyage a besoin d’un programme prenant en entrée un nom de VILLE, et affichant la table contenant la reponse à la question:
Donner les couples (nom de client, identifiant de sejour) tel que ce sejour est dans la VILLE, et propose l’activité favorite de ce client.
Exemple:suggestion_client(VILLE = 'Oahu')
Sortie:
VILLE
NOM
IDS
Oahu
Kelly
12
Oahu
Dupond
12
Le but de l’activité est de comprendre les différentes étapes utiles à ce programme.
Créer une table unique CHOIX_SEJOUR vide avec toutes les colonnes des 2 tables.
Pour chaque ligne de CHOIX_SEJOUR, coller bout à bout les lignes de SEJOUR et de CLIENTS ayant la même ACTIVITE. Représenter cette table. Il peut y avoir plusieurs clients pour un même sejour. Dans ce cas, il doit y avoir une ligne unique pour chaque coupe sejour-client.
Dans cette table CHOIX_SEJOUR, conserver uniquement les lignes correspondant à la ville Oahu.
Créer une nouvelle table RESULTAT à partir de CHOIX_SEJOUR en ne conservant que les colonnes VILLE, NOM, IDS. Représenter cette table.
Attribuer à chaque instruction le nom de l’opération réalisée. Choisir parmi:
Jointure
Projection
Selection
Modification de table
COURS
Tables - généralités
Une table
Une table est une liste de lignes, dont les éléments partagent les mêmes colonnes (descripteurs).
Une ligne
Chaque ligne est un p-uplet de valeurs (duet, triplet, …)
Une colonne
Dans chaque colonne, on trouve des valeurs de même type: le domaine de valeurs.
Chaque colonne porte un nom: le descripteur de la colonne.
Le schéma d’une table
Le schema d’une table est sa structure. C’est l’ensemble de ses descripteurs de colonnes avec leur type. C’est ce qui décrit une table.
Exemple: Donner le schema de la table clients
IDC : entier
NOM : caracteres
AGE : entier
ACTIVITE : caracteres
Le contenu d’une table
Le contenu d’une table est formé de ses lignes, qui contiennent les valeurs
L’identifiant ID
Parmi les colonnes, l’une d’entre-elles a un statut particulier: L’IDENTIFIANT. Celui-ci doit être unique pour chaque entité, et pour chaque ligne.
Représenter une table
On peut représenter une table sous forme de texte structuré: en csv, json, ou xml.
Ces formats sont interopérables. On peut les manipuler avec de nombreuses applications. (tableurs, langages informatique).
Table mise dans une liste python
Pour ouvrir et lire un fichier csv en langage python, on peut utiliser le script suivant:
On suppose que la table a été importée dans une liste de dictionnaires. Le traitement affectera TOUTES les lignes de la table.
Calculer une moyenne
parcourir tous les elements de liste
ce sont des dictionnaires: selectionner la valeur associée à la clé
faire la somme et diviser par le nombre d’éléments de la liste. (le nombre de dictionnaires)
appel de la fonction avec le tableau
tableau=[{'IDC':27,'NOM':'Ritta','AGE':19,'ACTIVITE: 'Danse'},{'IDC':19,'NOM':'Blaise','AGE':29,'ACTIVITE: 'Cinema'},{'IDC':11,'NOM':'Dede','AGE':59,'ACTIVITE: 'Nature'}]defmoyenne(L,cle):"""calcule la moyenne des valeurs associées à clé
params:
L: list of dict
cle: str, la clé commune à chaque dictionnaire, les valeurs associées
sont soit int soit float
"""s=0foreleminL:s+=elem[cle]returns/len(L)>moyenne(tableau,'AGE')35.666667
Ajouter une valeur calculée
On peut souhaiter ajouter la différence avec la moyenne des âges, pour chaque élément du tableau. Il faudra:
calculer la moyenne des âges (fonction moyenne)
parcourir les dictionnaires du tableau
lire la valeur associée à âge
valeur = moyenne(L,'AGE') - elem['AGE']
ajouter le couple 'DIFFERENCE': valeur pour chaque element du tableau
Opérations sur les tables: selection, projection, jointure
Ces opérations vont créer une nouvelle table.
Selection
Definition: Selectionner revient à extraire les lignes d’une table qui satisfont un critère. Pour réaliser une selection, on utilise une fonction test qui prend en paramètre une ligne de la table et retourne un booléen:
Definition: Une projection revient à ne conserver que certaines colonnes de la table. Pour réaliser une projection, on créé une nouvelle table:
Méthode utilisant une boucle bornée et une table de listes:
projection=[]colonnes=[0,1]# liste de colonnes à conserverforligneintable:nouvelle_ligne=[]foriincolonnes:nouvelle_ligne.append(ligne[i])projection.append(nouvelle_ligne)
Méthode utilisant une boucle bornée et une table dictionnaires:
table=[{'id':0,'NOM':'Jean','AGE':65},{'id':1,'NOM':'Michel','AGE':45},{'id':2,'NOM':'Manu','AGE':40}]projection=[]colonnes=['id','NOM']# liste de colonnes à conserverforligneintable:nouvelle_ligne={}foriincolonnes:nouvelle_ligne[i]=ligne[i]projection.append(nouvelle_ligne)>>>projection[{'id':0,'NOM':'Jean'},{'id':1,'NOM':'Michel'},{'id':2,'NOM':'Manu'}]
Definition: Une jointure est la fusion de 2 tables pour un même attribut. (commun).
La jointure permet de regrouper des informations dans une même table.
Internet manipule deux types d’information : les contenus envoyés et les adresses du destinataire et de l’émetteur. Ces deux types d’information sont regroupés dans des paquets de taille fixe, de façon uniforme et indépendante du type de données transportées : texte, images, sons, vidéos, etc.
Principe du modèle OSI
On peut rentrer un peu plus dans le détail du modèle OSI et en particulier de la communication TCP/IP.
Le modèle OSI est une norme qui préconise comment les ordinateurs devraient communiquer entre eux avec 4 couches technologiques adjacentes, numérotées selon leur distance au support d’emission (la couche n°1). On peut rassembler les couches 5, 6 et 7 en une seule.
Les couches forment une hiérarchie qui va de l’application (HTTP, FTP etc…) jusqu’au support physique (cable coaxial, ondes etc…).
Ce modèle OSI (un modèle theorique) a été conçu pour cloisonner les différents processus, langages et technologies employés.
Combien de couches?:
Selon le degré de description, on parle plutôt du modèle TCP/IP en 4 couches.
SSH et SSL sont deux technologies qui permettent de chiffrer et d’authentifier les données qui passent entre deux ordinateurs. Ce sont des applications de la couche 5. Ces données sont chiffrées avant leur mise en forme pour le transport. Pour approfondir: différence entre SSH et SSL.
Quelles sont les liens entre couches?
Le modèle OSI ajoute deux règles plus générales entre les couches :
chaque couche est indépendante ;
chaque couche ne peut communiquer qu’avec une couche adjacente.
Lors de l’émission d’une requête par une application, celle-ci doit traverser toutes les couches, depuis la 7 (application), puis de la 4 vers la 1; durant le trajet les données subiront des modifications et chaque couche rajoutera ce qu’elle voudra (généralement des en-têtes) pour mieux exercer sa fonction, mais pas seulement (la couche 1, de transport concerne… le transport).
Ce mécanisme s’appelle l’encapsulation : la trame de données numériques est constituée de plusieurs parties distinctes et mises dans un ordre particulier. L’encapsulation, en informatique et spécifiquement pour les réseaux informatiques, est un procédé
consistant à inclure les données d’un protocole dans un autre protocole.
Au final, ce qui va circuler sur le réseau est une trame de couche 1, qui contient le datagramme de couche 2 (qui lui-même contiendra le segment de couche 3)
encapsulation
Lors de la réception c’est exactement l’inverse qui se produit (désencapsulation).
desencapsulation
Prenons un exemple simple, vous demandez à votre navigateur de charger votre site préféré www.informatix.fr. Vous êtes reliés à un modem par un câble à paires torsadées.
couche application
Le navigateur demande au système d’envoyer une requête HTTP (couche 7). Dans cette couche, le logiciel lui même n’en fait pas partie. Cette couche concerne l’interface entre le logiciel est la couche de transport, et transporte l’information du protocole application utilisé (ici http par exemple, c’est à dire le protocole lié à l’affichage des pages html)
Sortie : [requête HTTP]
couche de transport
La requête arrive dans TCP qui ajoute son en-tête. Le protocole TCP va mettre en forme les données à envoyer et ajouter son en-tête. Ici, les numeros d’identification sont les port source et le port destination, qui identifient les applications qui entrent en jeu dans la communication. Parmi les informations, on trouve aussi le numéro de séquence initial, ISN, appelé aussi SYN (pour dire à la machine en face combien de données elle est censée avoir reçues) et celui d’acquitement ACK (le numéro du prochain octet des données attendues). Ces numéros vont permettre d’établir une communication avec accusés de reception (pour TCP, pas UDP) et de s’assurer, en principe, de l’identité de la machine avec qui les données sont échangées (avec le numéro de séquence, nécessaire pour l’accusé de reception). L’en-tête contient aussi un checksum. Pour résumer, on appelera cette en-tête le PDU (Protocol Data Unit).
Le segment TCP arrive dans IP qui ajoute aussi son en-tête (qui contient entre autres votre adresse IP (pour le routage) et celle du serveur demandé). La couche 3 indique à la couche 2 quel protocole a été utilisé (TCP, UDP…). Il y a aussi un numéro de connexions établies (IPID) sur le port en question et d’autres informations qui servent à l’eventuelle fragmentation du datagramme (les données ne peuvent pas exceder 1500 octets.
Une autre valeur transportée est le TTL (time to live) qui evite que le paquet ne circule indefiniment sur les reseaux.
Sortie : [en-tête IP][en-tête PDU][requête HTTP]
modèle simplifié du datagramme
couche physique
Le paquet IP arrive dans Ethernet qui ajoute un en-tête (qui contient entre autres votre adresse MAC - pour le switch - et celle du modem) et un checksum (vérification d’erreurs CRC). La couche 2 peut alors former la trame et l’envoyer sur le réseau.
Il va ajouter l’adresse MAC de l’emetteur et du destinataire, qu’il aura résolu grâce aux tables de routage et la table arp (côté serveur).
Sortie : [en-tête Ethernet][en-tête IP][en tête PDU][requête HTTP][checksum Ethernet]
en-tête Ethernet
Le document complet sur la structure d’une trame: Lien. document est issu du cours en ligne du lycee de Taaone, série technologique.
Lors du transport, chaque machine va désencapsuler les informations de la partie Ethernet et les remplacer par de nouvelles informations pour assurer le transport jusqu’à la prochaine étape.
Seule la machine de destination va acceder au contenu.
Le switch fait partie des couches liaison (2) et physique (1). Il a accès aux bits et à l’adresse MAC. Il en a besoin pour commuter les trames vers le bon port. (même reseau).
Le routeur a accès aux adresses MAC et IP de la trame. Il va interconnecter des reseaux grace aux adresses IP.
Protocoles de la couche physique
le rôle principal de la couche 1 est d’offrir un support de transmission pour les communications. Le protocole de la couche 1 doit permettre aux machines de communiquer sans collision (l’une après l’autre pour 2 machines de la même ligne). Il existe par exemple le protocole CSMA/CD, pour organiser le droit de parole lorsque 2 machines sont directement connectées.
Protocoles de la couche liaison
Le protocole Ethernet: l’objectif est de permettre à des machines connectées ensemble de communiquer, ainsi que la détection des erreurs de transmission.
Les données sont mises dans une trame, dont les premières valeurs lisibles sont l’adresse MAC du destinataire, puis de l’émetteur.
Ainsi, lorsqu’une machine reçoit une trame, et que les premiers bits identifient son adresse MAC, alors elle conserve la trame, car celle-ci lui est destinée.
Un autre protocole a été utilisé pour fiabiliser la transmission. Le protocole du bit alterné est utilisé au sein de la couche 2 du modèle OSI (distribution des trames Ethernet). Simple et léger, il peut toutefois être facilement mis en défaut, ce qui explique qu’il ait été remplacé par des protocoles plus performants.
source:
Cela necessite d’ajouter 1 bit dans l’en-tête prévu pour la couche 2, contenant déjà les adresses MAC.
Principe du protocole du bit alterné
la première trame envoyée par A aura pour drapeau 0, dès cette trame
reçue par B, ce dernier va envoyer un accusé de réception avec le même drapeau 0. Dès que A reçoit l’accusé de réception avec le drapeau à
0, il envoie la 2e trame avec un drapeau à 1, et ainsi de suite…
Le système de drapeau est complété avec un système d’horloge côté émetteur. Un “chronomètre” est déclenché à chaque envoi de trame, si au bout d’un certain temps, l’émetteur n’a pas reçu un acquittement correct (avec le bon drapeau), la trame précédemment envoyée par l’émetteur est considérée comme perdue et est de nouveau envoyée.
Code de correction d’erreur CRC
Dans la trame, on ajoute aux données de la couche 2 un code de correction des erreurs, ou CRC. C’est une valeur mathématique qui est représentative des données envoyées.
Lors de l’envoi, A calcule le CRC (une valeur X) et le met à la fin de la trame.
B reçoit le message et fait le même calcul que A avec la trame reçue (une valeur Y).
B compare la valeur qu’elle a calculée (Y) avec la valeur que A avait calculée et mise à la fin de la trame (X).
Si elles sont égales, bingo ! La trame envoyée par A est bien identique à la trame reçue par B.
Désencapsulation
Supposons que les machines A et B soient des routeurs:
Une fois que la machine B a reçu la bonne trame, elle désencapsule les données pour consulter celles de couche 3, les adresses IP. Elle agit alors selon le protocole IP.
Le protocole IP
Le protocole IP a pour charge de mettre en contact 2 ordinateurs qui n’appartiennent pas au même réseau. (par exemple sur Internet). C’est un protocole de la couche 3 (couche reseau).
La couche 3 a pour rôle d’interconnecter les reseaux.
Lorsqu’un routeur reçoit un paquet d’une machine A, et qu’il doit la transmettre vers la machine B, il consulte sa table de routage pour l’envoyer par le chemin (l’interface) le plus court.
La table contient, pour chaque machine à atteindre, l’interface vers laquelle doivent transiter les données, ainsi qu’un coefficient correspondant au coût pour cette interface. (Le coût étant égal au nombre de sauts, ou bien au résultat d’un calcul mettant en jeu le debit).
réseau de routeurs et table de routage (MOOC de l'IMT)
Cette table de routage ne peut contenir tous les routeurs du reseau internet (estimé à probablement 1 million). Il est donc necessaire de regrouper les sous-réseaux en aires, et d’indiquer le chemin vers ces aires dans les tables de routage.
La manière avec laquelle les tables de routages sont constituées est le resultat du protocole IP. Il existe ainsi:
TTL: Le protocole prend en compte le time to live (TTL), une valeur numerique du datagramme (couche reseau), qui diminue d’une unité à chaque saut (routeur). Lorsque ce TTL arrive à zero, alors que le paquet n’est pas parvenu à destination, celui-ci est détruit. On verra que dans le protocole TCP, cette eventualité est prévue. Un compte à rebours du côté de la machine emettrice va provoquer la ré expedition du paquet lorsque ce compteur arrive à 0, et qu’aucun accusé de reception n’est parvenu.
Le protocole TCP
L’hôte source va créer une session de connexion avec l’hôte distant (protocole HTTP). Une fois la connexion établie, l’échange de données commence. C’est le protocole TCP qui va s’assurer que tous les paquets sont bien transmis. Cette connexion est maintenue jusqu’à ce qu’elle soit fermée. voir sur it-connect.fr
Le protocole TCP permet d’assurer le transport des données de sorte que celles-ci arrivent complètes, sans trop occuper les lignes du reseau. C’est le protocole de la couche 4. A ce niveau de la couche de transport, l’identifiant ajouté au message est le numéro de port de l’application qui est à l’origine du message.
La fiabilité est obtenue par un mécanisme d’acquittement des segments :
À l’émission d’un segment, une alarme est amorcée
Elle est désamorcée quand l’acquittement correspondant est reçu
Si elle expire, le segment est réémis
TCP1
Chaque segment possède un numéro de séquence SEQ: c’est le numéro du premier octet envoyé. C’est grâce à ce numero que les segments peuvent être remis dans l’ordre.
Les acquittements sont identifiés par un marqueur ACK: c’est le numéro du prochain octet attendu par la machine.
Le concept même d’acquittement impose des notions de délai.
Par exemple, quel est le délai au delà duquel un segment non acquitté doit être réémis (typiquement 30’ à 1min).
TCP effectue une tâche importante: le multiplexage/demultiplexage: c’est à dire, faire transiter sur une même ligne, en série, des données qui sont à priori en parallèle, non hierachisées (une page web constituée de différents fragments, …). Ces données sont alors reconstruites, grâce au format utilisé pour leur transport. Voir le detail du modèle OSI
TCP2
TCP permet ainsi d’être un protocole fiable sans perte de paquets, qui permet à 2 machines de communiquer entre elles (et seulement 2)
La communication serveur-client est-elle toujours synchrone?
Cette attente de l’acquittement est pénalisante, sauf si on utilise un mécanisme de « fenêtres glissantes», comme le suggère la figure suivante:
Les fragments peuvent être envoyés quasi simultanément, sans attente de l’acquittement. La couche TCP du destinataire aura toute l’information pour le replacer dans le bon ordre. À chaque paquet est associée une horloge. Si l’un des paquets n’est pas acquité dans les temps, il est réémis
Avec ce principe, la bande passante du réseau est beaucoup mieux employée.
Protocoles DNS, HTTP, …
C’est un protocole de la couche Application. Le sujet a déja été traité ici
La couche d’application définit les services Internet standard et les applications réseau à la disposition des utilisateurs: utilise les protocoles HTTP, FTP, SMTP.
1.(QCM) Depuis la machine MACH02, à l’aide de quelle commande peut-on tester le dialogue entre ces deux machines ?
Réponses :
A- ping 172.16.100.201
B- ping 172.16.100.202
C- ping 172.16.100.254
D- ping 255.255.0.0
2. On souhaite ajouter une nouvelle machine dans ce reseau. Proposez une nouvelle adresse IP possible pour cette machine.
3.(QCM) Quel est le composant qui a l’adresse 172.16.0.254?
A- un ordinateur du reseau
B- l’une des interfaces du routeur
C- l’adresse du switch
Ex 2:
Une machine a pour adresse IP:
$$192.168.0.1 / 24$$
le /24 signifie que les 24 premiers bits correspondent à l’adresse reseau. Le reste des bits correspond à l’adresse machine.
Représenter cette adresse en binaire, et identifier les bits correspondant aux 2 sous-parties, reseau et machine.
Constitution d’un reseau
Ex 1:
1. La machine 192.168.0.1 veut joindre la machine 10.0.1.1 Combien de sauts seront necessaires?
2. Les switchs ne sont pas représentés sur ce schéma. Positionnez celui du reseau 192.168.0.0
3. Les ordinateurs du reseau 192.168.0 ne peuvent plus acceder à internet, de même que celui d’adresse 10.0.0.1. Par contre, ceux-ci peuvent encore communiquer entre eux. Quelle peut être la cause de cette panne?
Routage
Ex 1:
Soit le reseau de routeurs A, B, C, D:
On suppose que la transmission par une liaison prend une unité de temps. Un seul paquet peut emprunter une liaison pendant cette durée.
A chaque unité de temps, le paquet poursuit sa route selon le parcours le plus rapide et fait 1 saut.
Au bout de ce temps, le paquet est donc forcément stocké au niveau du routeur d’arrivée.
A l’instant 1, A commence l’envoi vers C d’une donnée constituée de 3 paquets P1, P2, P3.
A l’instant 2, D commence l’envoi vers C d’une donnée composée de 2 paquets P4 et P5
Temps
A
B
C
D
0
P1, P2, P3
1
P2, P3
P1
P4, P5
2
…
1. Compléter le tableau des différentes étapes d’envoi des données.
2. Déterminer l’espace de stockage nécessaire dans le noeud B.
Trame et datagramme
Ex 1:
Commenter le schéma précédent en expliquant l’encapsulation des données.
Donner les principaux éléments qui composent un datagramme IP et décrire leur utilité.
Ex 2:
Voici le modèle simplifié de datagramme IP que nous allons utiliser dans la suite de l’exercice:
modèle simplifié de datagramme IPv4
1. Sur combien d’octets sont codés:
une adresse IPv4?
une adresse IPv6?
un entête IPv4 (au minimum)?
2. En vous basant sur l’illustration du datagramme IP ci-dessus, dessinez et indiquez certaines des valeurs contenues dans un 2e datagramme qui repond à l’emetteur avec la donnée: il est midi, le TTL est fixé à 5.
3. Représentez le datagramme IPv4 correspondant aux informations suivantes:
source: 10.0.1.1
destination: 128.192.2.2
TTL: 3
Données à envoyer: Bonjour
Pas d’option
Protocole du bit alterné
Ex 1:
On veut envoyer la donnée 1234567890 de A vers B avec le protocole du bit alterné
1. Que doit renvoyer B lorsqu’il reçoit:
donnée: 12345
bit de contrôle: 1 ?
2. Que doit renvoyer A s’il reçoit un bit de contrôle à 0?
3. Que doit-il renvoyer s’il reçoit 1 comme bit de contrôle?
Ex 2:
La machine A doit envoyer les 3 données suivantes: hohoho, salut, les enfants.
Indiquer les données et les bits de contrôle qui sont transmis dans le protocole du bit alterné lorsque:
a. toutes les données sont transmises sans problème.
b. la 2e donnée est mal receptionnée 2 fois de suite.
Protocole TCP
Ex 1: (QCM)
Quels sont les avantages de la transmission sous forme de paquets?
A- S’assurer que les données arrivent dans leur ordre d’envoi.
B- S’assurer que les données ne restent pas indéfiniment dans le réseau.
C- Utiliser au mieux les liens dans le reseau.
Ex 2: (QCM plusieurs reponses possibles)
Que nécessite la transmission sous forme de paquets?
A- Pouvoir stocker la donnée si un lien n’est pas libre.
B- Une adresse source et une adresse destination associée au paquet.
C- Un protocole de fiabilisation de la transmission.
Un reseau, c’est quoi? C’est un système constitué de machines reliées ensembles (machines de tout genre: ordinateur, imprimante,…). Elles ont une adresse IP.
L’adresse IP (Internet Protocol) identifie un périphérique à l’intérieur d’un réseau. A l’intérieur de ce réseau elle est unique.
Les outils utilisés en simulation ne fonctionnent pas tous en mode réel, à partir de votre propre ordinateur du lycée, à cause de restrictions nécessaires pour des problèmes de sécurité.
TP Filius 1 : faire communiquer 2 ordinateurs (durée indicative: 10 min)
Lancer le logiciel Filius.
On réalise un premier réseau simple de 2 ordinateurs reliés par une seule ligne.
Disposer les 2 ordinateurs comme présenté sur la video.
Modifier les adresses IP de ces ordinateurs pour avoir, dans l’ordre:
192.168.0.1
192.168.0.2
Remarque: Souvent, dans un même reseau, les 3 premiers octets de l’adresse IP des machines sont identiques. (ici: 192.168.0). Seul le dernier octet change. Pour l’une des machines, ce sera .1, pour la suivante .2, etc…)
Relier ces ordinateurs
Installer les logiciels utiles pour faire communiquer ces machines. Pour faire cela: Démarrer la simulation:
Puis faire un double clic sur chacune des machines, et installer le logiciel ligne de commandes.
console d'installation de logiciels
tester alors les commandes suivantes depuis la machine M1:
ipconfig : vérifier la correspondance de l’adresse IP de la machine M1
ping 192.168.0.2 : pour établir et tester une connexion avec la machine M2
traceroute 192.168.0.2 : pour établir le trajet qui mène jusqu’à M2
Tester alors les commandes ping et traceroute vers une adresse de machine inexistante dans le réseau. Par exemple 192.168.0.3
Qu.1a: comment voit-on si le chemin vers une machine du reseau existe? Quelle information lit-on dans la console?
modifier le réseau et mettre 3 ordinateurs reliés à un switch (un connecteur) : voir la vidéo pour explications
revenir en mode conception du reseau (bouton avec le marteau)
commencer par supprimer le cable (clic Droit sur le composant => Supprimer)
ajouter l’ordinateur M3. Modifier son IP en 192.168.0.3. Relier ces machines à l’aide d’un switch.
tester alors la commande de traceroute entre M1 et M3
Qu.1b: Pourquoi a-t-on besoin d’un switch dans un réseau à 3 ordinateurs?
TP Filius 2 : créer un reseau de type lycée (durée indicative: 20 min)
On cherche maintenant à créer un système de 2 sous-réseaux locaux. Ces reseaux auront pour adresses: 198.168.0.0 et 192.168.2.0
C’est à dire que toutes les machines du réseau 198.168.0.0 auront en commun les 3 octets 198.168.0 et toutes les machines du reseau 198.168.2.0 auront en commun les octets 198.168.2.
Le sous-réseau 192.168.2.0 comportera un switch et 3 ordinateurs M4, M5 et M6. Ces machines auront pour adresses IP:
192.168.2.1
192.168.2.2
192.168.2.3
Votre système devrait ressembler à l’image suivante:
systeme de 2 sous-reseaux sans routeur
Tester alors la commande ping depuis la machine M1 vers celle M6 du 2e sous-reseau.
Qu.2a:: La machine M6 est-elle accessible depuis M1? Pourquoi?
Modifier le système en ajoutant un routeur:
clic droit sur le Switch2 : faire supprimer tous les cables
ajouter le routeur
paramétrer le routeur:
clic sur le routeur
renseigner les adresses des 2 reseaux sur l’interface du routeur:
192.168.0.254 du côté du reseau 192.168.0.0 (à gauche)
192.168.2.254 du côté du reseau 192.168.2.0 (à droite)
adresses des reseaux
cocher routage automatique:
option routage automatique
Pour chacun des ordinateurs du sous-reseau 1, M1, M2, M3, renseigner l’adresse de l’interface reseau 1 du routeur: mettre 192.168.0.254 dans le champs passerelle. Ce sera l’adresse IP de la carte reseau du routeur, du côté du reseau 192.168.0.0 (on met 254 à la place de 0 pour l’adresse routeur).
renseigner l'adresse reseau pour chaque ordinateur
Même travail pour M4, M5, M6: renseigner la passerelle 192.168.2.254
refaire le cablage
Qu.2b: Pourquoi le routeur de votre système informatique possède t-il 2 adresses IP?
Qu.2c: Démarrer le système et tester alors la commande ping de M1 vers M6, puis de M6 vers M1. Que constatez-vous? Pourquoi?
Qu.3a. Représenter sur votre feuille le reseau en ne dessinant que les ordinateurs n°1 et n°15, ainsi que tous les routeurs traversé (plus court schemin entre M1 et M15).
Qu.3b. Indiquer sur le schéma, pour chaque routeur, l’adresse passerelle que le message de M1 vers M15 va emprunter.
Lancer la simulation
Prendre connaissance de l’adresse IP de l’ordinateur n°15
Depuis l’ordinateur n°1: Lancer le logiciel Ligne de commande
Faire: traceroute suivi de l’adresse IP de la machine 15
Repérer alors quels sont les adresses passerelles empruntées par les données entre ces 2 ordinateurs.
Qu.3c. Quel est le nombre de sauts entre M1 et M15? Est-ce que le nombre de sauts effectués vous semble cohérent?
Qu.3d. S’agit-il des mêmes adresses passerelles lorsque la machine M15 envoie un message à M1? Vérifiez le par une expérience.
Table de routage
Revenir en mode edition (marteau) : cliquer sur le routeur A
Dans l’onglet général : décocher l’option : routage automatique
Aller dans l’onglet table de routage (forwarding table):
table de routage du routeur A
Q3e : cartes reseaux du routeur:
Hormis l’interface 127.0.0.1 : Combien d’interfaces différentes possède le routeur? (colonne NIC, next interface connection)
Quels sont les 3 réseaux auquel ce routeur est directement relié ? Donner leur adresse IP.
Serveur web
TP n°4: (optionnel) Créer une page web (durée indicative: 30 min)
si vous n’avez pas le temps, passez cette étape et rendez vous directement au chapitre communication client-serveur
En mode simulation:
Ajouter à l’ordinateur n°15 les logiciels:
explorateur de fichiers
editeur de fichier
webserveur
webbrowser
Sur l’ordinateur n°15:
lancer l’explorateur de fichiers
aller dans le dossier webserver: effacer tous les fichiers présents
lancer le logiciel editeur de texte
Saisir une ou plusieurs instructions en html, comme par exemple:
machine n°15:
cliquer sur le bouton Fichier
machine n°15:
sauvegarder ce fichier dans le dossier webserver. Choisir: Nom de fichier: index.html
Ouvrir le l’app webserveur et démarrer (Start)
test en local:
ouvrir le webbrowser. Dans la barre d’adresse, saisir http://localhost.
Qu.4a.: Voyez vous votre page? Expliquer alors ce signifie l’adresse localhost.
Aller sur l’application webserver: Les informations affichées devraient montrer l’entête HTTP avec la requête reçue (méthode GET, …), l’entête de la reponse (HTTP/1.1 200 OK), ainsi que le script HTML téléchargé.
Qu.4b.: Recopier l’entête sur votre feuille. S’agit-il d’informations de la couche 4 (Application), 3 (Transport), 2 (reseau), ou 1 (accès au reseau)? voir ici les rappels de cours de 1ere NSI
Ajouter à l’ordinateur n°1 le logiciel : Navigateur Web
Lancer le Navigateur web
Dans la barre d’adresse, completer http:// avec l’adresse IP de l’ordinateur n°15 et cliquer sur Afficher
Si la page ne se charge pas la première fois, fermer et rouvrir le serveur du poste 15, ainsi que le Navigateur Web côté client.
Comme pour la connexion en localhost: Lire les informations de la fenêtre de l’application Webserver:
Qu.4c: Quelles informations ont changé sur la fenêtre de l’application webserver?
TP n°5: Communication client-serveur (durée indicative: 10 min)
Quitter la simulation précédente et ouvrir le nouveau reseau filius. Télécharger et ouvrir le fichier
Le reseau contient maintenant 2 serveurs (192.168.5.3 et 192.168.4.3).
Sur les ordinateurs 192.168.5.3 et 192.168.4.3, lancer le logiciel Webserveur. Laisser celui-ci ouvert.
Sur l’ordinateur client M1, ouvrir le navigateur. Saisir comme adresse http://192.168.5.3. Vous devriez obtenir une page web (en allemand…)
Sur le serveur 192.168.5.3, la fenêtre de son logiciel devrait montrer la requête reçue, et la reponse transmise.
Qu.5a: d’où vient la page affichée par le navigateur de la machine M1? Recopiez sur votre feuille l’en-tête HTTP affichée par le logiciel serveur. (pas le contenu html de la page).
Qu.5b: Même question, mais cette fois à partir d’une connexion sur le serveur 192.168.4.3
TP n°6: Serveur DNS (durée indicative: 20 min)
Quitter la précédente simulation et ouvrir le fichier avec les tables DNS
Le reseau contient maintenant 2 serveurs (192.168.5.3 et 192.168.4.3) ainsi que 2 serveur DNS.
Le BON serveur DNS a pour adresse 192.168.6.1
Qu.6a En mode construction, relever l’adresse DNS renseignée pour tous les ordinateurs
En mode simulation : vous allez commencer par démarrer chacun des serveurs.
Vérifier que la table pour la resolution par le serveur DNS 192.168.6.1 est remplie comme indiqué ci-dessous. (sinon, complétez la).
IP
adresse symbolique
192.168.4.3
estiennedorves.fr
192.168.5.3
autreserveur.com
configuration DNS
Puis, à partir de l’une des machines du reseau, comme par exemple M1, vous allez vous connecter à chacun de ces serveurs, à partir de leur adresse symbolique.
navigation avec adresse symbolique
Qu.6b: Expliquer quel est le principe du protocole DNS.
Le protocole DNS est vulnérable, et peut faire l’objet d’un piratage: voir explications ici: site cloudfare.com
Qu.6c: Quelle est la table du serveur DNS pirate ?
Qu.6d: Comment peut-on utiliser la simulation réalisée sur Filius pour réaliser le scénario d’un piratage de DNS? Quelles sont les différentes étapes à suivre sur le logiciel Filius?
DNS et configuration de votre poste informatique
Constituer une table de correspondance entre nom de domaine et adresse ip sur le site https://www.my-ip-finder.fr et choisir l’onglet DNS lookup :
Copier les commandes une à une dans un fichier d’extension .bat et executer le fichier.
On peut rediriger la sortie de chacune des commandes dans un fichier .txt
ipconfig /all >R1.txt
traceroute x >>R1.txt
a. Avec ipconfig, retrouver l’adresse du serveur DNS utilisé
b. Avec traceroute, combien de sauts sont necessaires pour joindre musee-orsay.fr?
Protocoles des couches 3 et 2
Protocole TCP (optionnel)
Côté client
Faire un clic droit sur la machine M1. Choisir show data exchange
Dérouler alors trames échangées jusqu’à arriver à celles de protocole TCP
Qu.4f: Dans la série de trames TCP:
L’adresse source et celle destination, sont-elles toujours les mêmes? Ou y-a-t-il une alternance?
Observer le détail de la première trame (ci-dessous): vous avez accès aux informations de la couche liaison (2), reseau (3), ainsi que la couche transport (4): identifier les informations pour chacune de ces couches: les informations pour chacune de ces couches: adresses mac (couche 1), IP et TTL pour la couche 2, SEQ et ACK pour la couche 3… rappels de 1ere NSI
Ces informations, évoluent-elles d’une trame à l’autre?
detail de la premiere trame
Protocole IP
Le document suivant présente la disposition des données dans un datagramme. Ce sont les informations transmises au niveau de la couche 2 du modèle OSI. (explications sur openclassrooms.com)
datagramme
Qu.4g: Quels sont les renseignements fournis sur l’image de la question 4f (détail de la première trame) que l’on retrouve des les champs du datagramme?
Compléments théoriques sur les adresses des machines
L’adresse IP(Internet Protocol) identifie un périphérique à l’intérieur d’un réseau. A l’intérieur de ce réseau elle est unique.
Une adresse (IPv4) est constituée de 4 nombres binaire de 8 bits chacuns (32 bits), comme par exemple:
$1100 0000.1010 1000. 0000 0000. 0000 0001$
Pour rendre la lecture plus facile, les séries de 8 bits seront traduites en leur valeur décimale correspondante, comprise entre 0 et 255 (voir le cours codage des nombres).
L’adresse binaire vue plus haut sera alors traduite en :
$192.168.0.1$
L’adresse possède 2 parties:
une partie identifie la machine
une autre partie identifie le reseau
Masque de sous-reseau
Masque de sous-reseau: c’est une serie de valeurs avec des 255 ou 0, ou autre sur le(s) dernier(s) octet(s).
La valeur correspondante binaire début donc par une série de 1, marquant les positions relatives à l’adresse reseau dans l’adresse IP.
Par exemple: L’adresse machine suivante est constituée d’une première partie reseau, les 24 premiers bits, puis de l’adressage machine dans le reseau (8 derniers bits):
$1100 0000.1010 1000. 0000 0000. 0000 0001 / 24$
Le masque de sous-reseau est alors:
$1111 1111.1111 1111. 1111 1111. 0000 0000$
Que l’on peut aussi écrire:
$255.255.255.0$
Machines appartenant à un même reseau
Definition: Deux machines sont sur le même réseau si et seulement si, la partie réseau de leur adresse IP est identique.
Les derniers caractères /24 correspondent au masque de sous-reseau. Ils signifient que le reseau contenant la machine a une adresse codée sur les 24 premiers bits (192.168.0). Et que les 8 derniers bits constituent l’adresse de la machine dans ce reseau (il s’agit donc du .1 final).
IPv6
Pour la norme IPv6, ce nombre est sur 128 bits, soit 16 octets.
Exemple d’adresse IPv6 exprimée en hexadécimal (32 caractères):2001:0db8:3c4d:0015:0000:0000:1a2f:1a2b
classes d’adresse IP
classe A : adresses IP comprises entre 0.0.0.0 et 127.255.255.255 masque 255.0.0.0 : on ne peut avoir qu’une toute petite partie sous-reseau mais beaucoup d’adresses machines. Un petit reseau de beaucoup de machines.
classe B : 128.0.0.0 à 191.255.255.255 masque sous-reseau de 2 octets : on met autant de machines que de sous reseaux.
classe C : masque sous-reseau de 3 octets: beaucoup de sous-reseaux et peu de machines.
Sur un reseau, deux adresses sont deja reservés: l’adresse de broadcast (bit adresse mis à 255), ainsi que l’adresse de reseau (bit d’adresse mis à zero). La plage adressable se situe entre ces 2 valeurs.
Adresse mac
Une adresse MAC (Media Access Control), parfois nommée adresse physique,
est un identifiant physique stocké dans une carte réseau ou une
interface réseau similaire. Elle est unique au monde
Une adresse MAC est codée en hexadécimal, sur 6 octets (cf cours sur l’hexadécimal)
00-1E-33-1D-6A-79 est une adresse MAC
=> Ouvrir l’invite de commande windows et entrer la commande ipconfig /all. identifier l’adresse MAC de votre ordinateur.
HTTP est un protocole de la couche Application selon le modèle de communication entre machines OSI (développé dans ce cours).
C’est le protocole qui permet de récupérer des ressources telles que des documents HTML. Il est à la base de tout échange de données sur le Web. C’est un protocole de type client-serveur, ce qui signifie que les requêtes sont initiées par le destinataire (qui est généralement un navigateur web).
Le protocole HTTP est un protocole synchrone: pour chacune des tâches, il faut attendre la réponse avant d’exploiter la ressource chargée.
Un document complet est construit à partir de différents sous-documents qui sont récupérés, par exemple du texte, des descriptions de mise en page, des images, des vidéos, des scripts et bien plus.
requêtes pour la construction d'une page web. Source: MDN Web Docs
Le navigateur web assemble alors ces ressources pour présenter un document complet à l’utilisateur : c’est la page web.
Pour obtenir ces fragments de page, le navigateur web envoie des messages qui sont appelés des requêtes et les messages renvoyés par le serveur sont appelés réponses.
Entre une requête et la réponse se trouvent de nombreuses entités qu’on désignera de façon générique sous le terme proxies. Celles-ci exécutent différentes opérations et agissent comme passerelles ou comme caches par exemple.
En réalité, il y a plus d’un ordinateur entre un navigateur et le serveur qui traite la requête : il y a les routeurs, les modems et bien plus. Grâce à la construction en couche du Web, ces intermédiaires sont cachés dans les couches réseau et transport. HTTP, lui, est bâti sur la couche applicative.
Pour plus de détails, voir la page sur MDN Web Docs.
naviguer sur le web
Une page web est un document hypertexte. Cela signifie que certaines parties sont des liens hypertextes qui peuvent être activés (généralement avec un clic de souris) afin de récupérer une nouvelle page web, permettant à l’utilisateur de naviguer sur le Web.
Encore une fois, c’est le navigateur qui traduit ces instructions en requêtes HTTP.
Ce protocole HTTP contrôle la façon dont le client formule ses demandes et la façon dont le serveur y répond, et connaît différentes méthodes de requête: GET, POST, HEAD, OPTIONS, TRACE, ou autres méthodes spécifiques.
Méthodes HTTP
HTTP est un protocole de la couche Application pour lequel le client et le serveur communiquent grâce aux en-têtes.
Pour la requête, c’est dans l’en-tête que la demande est formulée.
Pour la reponse, le serveur ajoute un en-tête, utile pour le protocole.
GET
c’est la méthode HTTP qui est la plus utilisée pour demander une ressource, par exemple un fichier HTML, au serveur Web. Dans le navigateur, on fait cette demande grâce à une URL (uniform ressource locator)
Si l’on saisit l’URL www.exemple.com/test.html dans la barre d’adresse du navigateur, celui-ci se connecte au serveur Web www.exemple.com et lui envoie la requête GET qui contiendra:
la méthode de communication client-serveur: ici GET
le chemin vers la ressource: /test.html
GET /test.html
Le serveur renvoie alors le fichier test.html.
Déroulé d’une requête HTTP par la méthode GET
Des paramètres d’URL qui peuvent être ajoutés à l’URL s’appelent chaine query, ou chaine de requête.
Une URL valide est alors construite de la manière suivante:
# nom de domaine symbolique
http://nom du domaine.org/chemin_vers_la_ressource?chaine query
La requête GET contient alors des informations supplémentaires que le serveur Web doit traiter.
Les règles de syntaxe employées:
La chaîne de requête est introduite par un « ? » (point d’interrogation).
Chaque paramètre est nommé, il se compose donc d’un nom et d’une valeur : « Nom=Valeur ».
Si plusieurs paramètres doivent être inclus, ils sont reliés par un « & ».
Par exemple, sur un site de météo, Nice est saisi comme ville et 12 comme heure UTC. L’URL saisie dans le navigateur pourrait être:
http://ma_meteo.fr/search?ville=Nice&UTC=12
Il se produit alors plusieurs étapes avant l’affichage de la page par le navigateur:
(1): saisie de l’URL dans la barre d’adresse (ou activation d’un lien depuis la page web)
le navigateur établit une connexion TCP avec le serveur du site ma_meteo.fr puis lui envoie la requête HTTP suivante:
GET /search?ville=Nice&UTC=12
(2): émission de la requêtte HTTP dans un format normalisé (ex. HTTP/1.1)
(3): la requête est parsée[voir ci-dessous]et interprétée par le serveur
(4): reponse du serveur avec un en-tête HTTP ainsi que le script html de la page demandée.
En réalité, pour des problèmes de standardisation, l’URL ne contient pas tout à fait les mêmes symboles, et l’extension de l’adresse (la chaîne Query) pourrait plutôt ressembler à: %2Fsearch%3Fville%3DNice%26UTC%3D12 (voir URL encoder.org
Definition du terme PARSE:
“Parser” signifie analyser et convertir un script en un format interne que l’environnement d’exécution peut interpréter. Il s’agit d’une analyse syntaxique. Un paragraphe de la page sur les variables en python est consacré à la manipulation d’une chaine de caractères, ainsi qu’à la méthode parse en Python.
inconvenients de la méthode GET
La méthode GET est la plus utilisée pour obtenir les ressources qui construisent la page Web dans le navigateur.
Cette méthode présente des limites lorsque cette page doit être personnalisée:
Avec la méthode GET, les données à envoyer au serveur sont aussi écrites dans l’URL.
Cela présente un avantage: Les paramètres de l’URL peuvent être enregistrés avec l’adresse du site Web. (utile pour un marque page, historique de navigation, enregistrer des pages Web contenant certains paramètres de filtrage et de tri, meteo avec conservation de la localisation…).
Le principal inconvénient de la méthode GET est l’absence de protection des données. Un deuxième inconvénient est sa capacité limitée : suivant le serveur Web et le navigateur, l’URL ne peut pas contenir plus de 2 000 caractères environ.
La méthode POST
Cette méthode n’écrit pas les paramètres de l’URL, mais les ajoute à l’en-tête HTTP (HTTP header)
Revenons sur l’exemple de la page meteo. Voici un aperçu des interactions possibles entre l’utilisateur et la page. Celle-ci pourrait présenter:
un champs de texte à remplir (Ville)
un menu déroulant (heure)
L’en-tête HTTP (HTTP header) pourrait alors avoir le contenu suivant:
Comparatif GET POST
GET
POST
Visibilité
Visible pour l’utilisateur dans le champ d’adresse
Invisible pour l’utilisateur
Marque-page et historique de navigation
Les paramètres de l’URL sont stockés en même temps que l’URL.
L’URL est enregistrée sans paramètres URL.
Cache et fichier log du serveur
Les paramètres de l’URL sont stockés sans chiffrement
Les paramètres de l’URL ne sont pas enregistrés automatiquement.
Comportement lors de l’actualisation du navigateur / Bouton « précédent »
Les paramètres de l’URL ne sont pas envoyés à nouveau.
Le navigateur avertit que les données du formulaire doivent être renvoyées.
Type de données
Caractères ASCII uniquement.
Caractères ASCII mais également données binaires.
Longueur des données
Limitée - longueur maximale de l’URL à 2 048 caractères.
Illimitée.
GET pour les paramètres d’un site Web (filtres, tri, saisies de recherche, etc.).
POST pour la transmission des informations, des fichiers, et des données de l’utilisateur.
Autres méthodes HTTP
La méthode HEAD
Utilisée pour interroger l’en-tête de la réponse, sans que le fichier ne vous soit envoyé immédiatement. C’est utile, par exemple, si des fichiers volumineux doivent être transférés : grâce à la requête HEAD, le client peut d’abord être informé de la taille du fichier et seulement ensuite décider s’il veut recevoir le fichier.
OPTIONS
Avec la méthode OPTIONS, le client peut demander quelles méthodes le serveur supporte pour le fichier en question. Ces méthodes autorisées sont contenues dans le champs d’en-tête “allow”.
TRACE
La méthode TRACE peut être utilisée pour tracer le chemin qu’une requête HTTP emprunte jusqu’au serveur puis jusqu’au client. Vous pouvez utiliser la commande tracert de Windows pour tracer vous-même cet itinéraire.
tracert www.exemple.com
HTTP header
HTTP header Côté client
Chaque requête HTTP formulée par le navigateur contient:
une premiere ligne constituée de: METHODE suivie du PATH (chemin vers la ressource) suivi de la version HTTP. Exemple: `GET /index.php HTTP/1.1
Puis vient le HTTP header.
Pour le client, voici les principales informations contenues dans le http header:
Champ d’en-tête
Signification
Exemple
Accept
Les types de contenu que le client peut traiter ; si le champ est vide, il s’agit de tous les types de contenu.
Accept: text/html, application/xml
Accept-Charset
Quels jeux de caractères le client peut afficher.
Accept-Charset: utf-8
Cookie
Cookie stocké pour ce serveur
Cookie: $Version=1; Content=23
Content-Length
Longueur en octets
Content-Length: 212
Content-Type
Type MIME: text/plain pour les fichiers texte, application/.. pour le reste
Content-Type: application/x_222-form-urlencoded
Date
Date et heure de la demande
Date: Mon, 9 March 2020 09:02:22 GMT
Host
Nom de domaine du serveur
Host: exemple.fr
Referrer
URL de la ressource à partir de laquelle la demande est faite (c’est-à-dire à partir de laquelle le lien a été créé)
Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/80.0.3987.132 Safari/537.36
HTTP header Côté serveur
Chaque reponse HTTP retournée par le serveur contient:
une premiere ligne constituée:
de la version HTTP
du code statut (200, 301, 404, …)
du message de statut (OK, …)
puis les différents champs de l’en-tête.
et enfin le contenu html ou autre.
Sur l’exemple suivant, on voit par exemple, sur la 1ere ligne:
HTTP/1.1 est la version valide du protocole HTTP.
200 OK est le code de statut. Il indique que le serveur a reçu, compris et accepté la demande.
Le serveur renvoie cet en-tête avec la page HTML
Explications pour les différentes lignes (les champs d’en-tête):
Content-Encoding et Content-Type fournissent des informations sur le type de fichier.
Age, Cache-Control, Expires, Vary et X-Cache font référence à la mise en cache du fichier.
Etag et Last-Modified sont utilisés pour le contrôle de la version du fichier livré.
Le terme « server » désigne le logiciel du serveur Web.
Content-Length est la taille du fichier en octets.
Classes de statut HTTP
erreur 404: page internet introuvable
Classe 1xx, codes d’information : si le code commence par 1, le serveur indique au client que la requête actuelle est en en train de se faire. Cette classe regroupe des codes en cours de traitement et d’envoi.
Classe 2xx, codes de succès : un code qui commence par 2 indique que la requête a abouti. Elle a été reçue par le client, comprise et acceptée. En conséquence, les codes 2xx du serveur sont envoyés en même temps que les informations des pages Web désirées. En général, l’utilisateur ne prend en compte que la page Web qu’il a chargé.
Classe 3xx, codes de redirection : un code 3xx indique que la requête a été reçue par le serveur. Cependant, le client doit encore provoquer une action complémentaire. Par exemple, le code HTTP 301 signifie changement d’adresse définitif : les informations demandées par le client ne se trouvent plus à l’adresse indiquée car celle-ci a définitivement changée. Le navigateur Internet peut aussitôt rediriger l’utilisateur à la nouvelle adresse.
Classe 4xx, erreurs du client : le code 4xx renvoie à une erreur commise par le client. Le serveur a reçu la requête mais ne peut pas l’exécuter. La réponse 404 signifie par exemple que la page Internet est introuvable.. En général, il s’agit d’une syntaxe erronée. En général, l’utilisateur est automatiquement dirigé vers une page HTML.
Classe 5xx, erreurs du serveur : Le code 5xx fait référence à une erreur commise par le serveur. Ces informations indiquent que la requête en question est complètement ou provisoirement impossible. Une page d’erreur HTML est également présentée.
HTTP: sécurité et confidentialité
Sécurité
La sécurité d’un protocole vise à ce que les communications ne soient pas exploitables pour quelqu’un qui intercepte le message.
Le protocole HTTP possède une version sécurisée des échanges: il s’agit de HTTPS.
confidentialité: HTTP, un protocole sans ETAT
Pour une communication client-serveur:
Un état est conservé entre 2 requêtes si l’utilisateur, le client, s’est identifié.
Un protocole sans état (en anglais stateless protocol) est un protocole de communication qui n’enregistre pas l’état d’une session de communication entre deux requêtes successives. La communication est formée de paires requête-réponse indépendantes et chaque paire requête-réponse est traitée comme une transaction indépendante, sans lien avec les requêtes précédentes ou suivantes.
Le protocole HTTP est donc un protocole synchrone, et sans état.
Des couches de protocoles avec et sans état:
Dans les différentes couches de protocoles de communication: le protocole HTTP (sans état) s’appuie sur le protocole TCP, un protocole avec état, qui s’appuie à son tour sur le protocole IP, un autre protocole sans état.
Les cookies permettent de conserver de l’information en passant par le procotole HTTP qui est lui “sans état”.
Les cookies, ce sont des données qu’un serveur envoie au navigateur web de l’utilisateur. Le navigateur peut alors le stocker localement, puis le renvoyer à la prochaine requête vers le même serveur. Typiquement, cette méthode est utilisée par le serveur pour déterminer si deux requêtes proviennent du même navigateur.
Cela permet:
Gestion des sessions
Logins, panier d’achat, score d’un jeu, ou tout autre chose dont le serveur doit se souvenir.
Par exemple, garder un utilisateur connecté.
Personnalisation
Préférences utilisateur, thèmes, et autres paramètres.
Suivi
Enregistrement et analyse du comportement utilisateur.
2. Protection des données
contrôle des cookies par l'utilisateur
Les cookies étaient auparavant utilisés pour le stockage côté client. Mais aujourd’hui, la tendance est plutôt d’envoyér ces données avec chaque requête. Cela a pour conséquence de partager ses données pour l’internaute. Son surf n’est plus complètement anonyme.
En application de la directive ePrivacy, les internautes doivent être informés et donner leur consentement préalablement au dépôt et à la lecture de certains traceurs
Les cookies ont un domaine qui leur est associé. Si ce domaine est le même que la page sur laquelle vous êtes, on parle de cookie interne (first-party cookie). Si le domaine est différent, on parle de cookie tiers (third-party cookie).
Oui, avec HTTPS, les en-têtes HTTP sont bien chiffrées — et c’est un point souvent mal compris!
Ce qu’il se passe réellement:
HTTPS = HTTP + TLS (Transport Layer Security)
Le chiffrement TLS s’applique à tout le contenu HTTP, c’est-à-dire :
✅ Les en-têtes (headers) — Host, Cookie, Authorization, User-Agent…
✅ Le corps de la requête (body)
✅ Les en-têtes de réponse du serveur — Set-Cookie, Content-Type…
✅ Le corps de la réponse
Ce qui reste visible (non chiffré)
Même en HTTPS, quelques informations transitent en clair :
Élément
Visible ? Pourquoi
Adresse IP du serveur
✅ Oui
Nécessaire pour le routage réseau
Port (443)
✅ Oui
Idem
Nom de domaine (SNI)
⚠️ Souvent oui
Échangé pendant la négociation TLS pour choisir le bon certificat
URL complète / chemin
❌ Non
Chiffré
En-têtes HTTP
❌ Non
Chiffrés
SNI (Server Name Indication) : lors de la poignée de main TLS (handshake), le client indique le nom de domaine cible. Cette information est traditionnellement en clair, bien que la technologie ECH (Encrypted Client Hello) commence à chiffrer cela aussi.
On peut souvent deviner le domaine (via le SNI ou l’IP), mais pas la page précise visitée (l’URL complète, les cookies, les paramètres…).
Schéma simplifié
[Couche réseau] IP source / IP destination → visible
[Couche TLS] Handshake TLS (certificat) → partiellement visible
[Couche HTTP] En-têtes + Corps → chiffré ✅
Travaux Pratiques:
Formulaire et protocoles de transmission
La vulnérabilité des services d’authentification web correspond aux faiblesses des protocoles d’authentification du web.
On traitera de ces problèmes avec le TP suivant: Lien
Le moniteur réseau du navigateur affiche des informations sur les requêtes effectuées (par exemple, au chargement d’une page).
Outils de developpement sous Chrome
Répondre aux questions suivantes sur le cahier
Faire une recherche sur un moteur de recherche pour trouver l’URL de la page d’accueil du site cité des sciences.
1. Lorsque vous lancez un recherche sur un moteur de recherche, celui-ci utilise t-il une méthode GET ou POST? Justifiez. Quel est l’intérêt d’utiliser cette méthode?
Aller sur la page d’accueil du site de: cité des sciences.
2. Ouvrir le moniteur réseau du navigateur.
3. Après avoir rechargé la page de cité des sciences, quel est le nombre de requêtes?
4. Ce nombre évolue t-il alors que vous laissez la page ouverte, sans aucune action de votre part?
5. Est-ce que toutes les requêtes sont de type GET?
6. Cliquer sur la première ressource téléchargée, accueil/. Vous obtenez alors le détail de la ressource.
Quelle est la différence entre les informations transmises par le Headers et celles transmises par le Reponse (ou Response)?
Pour l’onglet Headers: S’agit-il du HTTP header émis par le client ou bien celui serveur? Justifier.
Reconnaitre et interpréter certains champs de l’en-tête.
7. Aller sur l’onglet Cookies pour cette première ressource. Que remarquez vous?
Y-a-t-il des ressources qui ont un code statut différent de 200? Quels sont-ils et que signifient-ils?
Quel est le nom de domaine qui revient le plus souvent pour ces requêtes, dont le statut est différent de 200?
Pour l’une de ces ressources, on observe en détail l’extension de l’URL que l’on appelle Query String (chaine Query). Celle-ci est écrite en Base 64. Elle est constituée de la série de caractères suivante:
Vol de cookies et détournement de session: kaspersky.fr
…Dans le cas du protocole HTTP, les fichiers cookies sont transmis en texte clair dans les en-têtes des requêtes HTTP, ce qui signifie qu’ils ne sont pas chiffrés. Un acteur malveillant (reseau wifi public) peut alors facilement intercepter le trafic entre vous et le site Internet sur lequel vous vous trouvez, et en extraire les cookies…
Peut-on utiliser cette technique pour bypasser le proxy du lycée? video youtube de 2015 => Non à cause des hebergements mutualisés, et de l’identification par l’en-tête host, necessaire pour la phase de présentation (https)
Ce TP a pour but d’illustrer ce qui arrive quand un utilisateur soumet un formulaire: où les données vont-elles et comment les gère-t-on une fois à destination? Nous examinerons aussi quelques problèmes de sécurité associés à l’envoi des données d’un formulaire.
img de MDN Sending_and_retrieving_form_data
Le formulaire en ligne
Il est conseillé d’utiliser le navigateur MOZILLA pour la clarté des renseignements fournis par les outils réseau.
Le bandeau de navigation permet de selectionner la méthode d’envoi des données:
méthode GET
méthode POST
authentification par cookie
Vous allez utiliser chacune des 3 méthodes. La procédure sera la même dans les 3 cas:
Ouvrir la fenêtre d’outils de développement du navigateur. Choisir l’outil réseau
Remplir et envoyer le formulaire
Une fois parvenu à la page “espace personnel”, vous allez explorer les éléments de la requête.
Dans la fenêtre de dev tools, l’outil réseau montre les différentes requêtes et ressources demandées. Dans cette liste, selectionner la page web (resaonline.la-bo.xyz). On peut alors procéder à l’analyse de l’URL. Cliquer sur le curseur devant GET.
inspecteur reseau sur Mozilla
L’URL permet de router notre requête vers le serveur correspondant au site web sur le réseau.
Un site Web est identifié selon une combinaison unique de:
son Adresse IP
un Numéro de port
le Host header (equivalent au nom de domaine)
Méthode GET
Dans la barre d’URL du navigateur. Recopier l’URL de la page demandée. Repérer les 3 sous parties: (se documenter: openclassroom, ou bien wikipedia)
le nom de domaine
le chemin
les paramètres query
la connexion vers le site, se fait-elle selon le protocole http ou bien https? Comment le voit-on? Peut-on modifier le protocole directement dans la barre d’adresse, en ecrivant http:// ou bien https:// avant le nom de domaine resaonline.la-bo.xyz
Dans la fenêtre réseau du dev tools: Repérer les informations du header (en-tête) pour cette requête (client):
méthode (vous devez lire en principe: GET)
la version HTTP (1.1? autre?)
L’identité du site Web serveur: voir plus haut (IP, Host header)
le chemin vers la ressource sur le serveur (path)
les paramètres query (Query String Parameters), s’il y en a.
Repérer les informations de la reponse à cette requête
code de statut (200 OK?)
Referrer: URL de la ressource à partir de laquelle la demande est faite (c’est-à-dire à partir de laquelle le lien a été créé)
Content-Type: informations sur le contenu du document chargé (txt, html, js, css, …?)
User-Agent: navigateur client
Recharger la page: le navigateur propose t-il de soumettre à nouveau le contenu du formulaire? Les informations du formulaire sont-elles toujours présentes dans la carte d’identité?
Dans l’historique du navigateur: le lien consulté contient-il les Query String Parameters?
Ecrire directement, dans la barre d’adresse une requête vers ce serveur en choisissant vous-même vos Query Parameters. Le serveur repond-il à votre requête?
Méthode POST
Répondre aux même questions (qu 1 à 6 de la méthode GET).
Méthode avec authentification par cookie
Dans les outils réseau du navigateur, chercher l’onglet cookie, et lire le contenu. Faire une copie d’écran dans votre document réponse. Comment les informations du formulaire sont-elles écrites dans le cookie? Sous une forme structurée?
exemple de capture d'écran de l'outil d'exploration du cookie
Recharger la page: le navigateur propose t-il de soumettre à nouveau le contenu du formulaire? Les informations du formulaire sont-elles toujours présentes dans la carte d’identité?
Dans un autre onglet du navigateur: saisir l’adresse http://resaonline.la-bo.xyz/getcookie. Les informations du formulaire sont-elles toujours présentes dans la carte d’identité?
Saisir maintenant cette adresse dans un AUTRE navigateur. Les informations du formulaire sont-elles toujours présentes dans la carte d’identité?
Rechercher le cookie grace aux options du navigateur. (Voir tuto sur cette page. Quels autres cookies ont été déposés lors de votre session (aujourd’hui)? Comment peut-on se debarrasser de ces cookies?
Conclure: Les traces numériques laissées sur mon ordinateur peuvent-elles contenir des informations sur mon identité numérique?
Sécurité sur le Web
Video: transfert encryptage ssl
Code Rock & Apprendre
Questions
Quel est le scénario mettant en jeu un cyberpirate proposé dans cette vidéo?
Est-ce que cela change quelque chose, de naviguer en http ou bien en https?
Request URL (which web page was requested by the client)
Website content
Query parameters
Headers
Cookies
Si votre échange avec le serveur est en https. Est-ce une bonne idée d’échanger des informations personnelles par la méthode GET si le site internet ne propose que la méthode GET? Pourquoi?
Conclure: Quels conseils peut-on donner à un utilisateur qui navigue et fait des achats sur le net?
page sur les requetes http sur le blog du professeur maximilienandile
tuto requests
Module request
Le module requests de python permet de recuperer les données d’une requete HTTP dans un format exploitable (dict,list).
La communication avec le serveur demande d’utiliser une clé, que vous devrez générer en créant un compte. (API key).
Données météo open source
L’exemple suivant traite de l’exploitation d’une requete sur le site OpenWeatherMap. Le compte gratuit permet de realiser quelques requetes, en nombre raisonnable, et sera suffisant pour developper un petit projet NSI.
Voici le script minimal
importrequests,json,sysAPPID='-- a remplacer par votre cle API et placer entre les guillemets--'#location = 'London,GB'location='Nice,FR'#Download the JSON data from OpenWeatherMap.org's API.url=f'https://api.openweathermap.org/data/2.5/weather?q={location}&appid={APPID}'response=requests.get(url)response.raise_for_status()#Uncomment to see the raw JSON text:#print(response.text)#Load JSON data into a Python variable.weatherData=json.loads(response.text)#Print weather descriptionsw=weatherDataprint(f'Current weather in {location}')print(w['weather'][0]['main'],'-',w['weather'][0]['description'])print()
Prolongement: Pour obtenir les prévisions sur plusieurs jours, utiliser la requete:
Le traitement va alors différer, car la météo des différents jours sera placée dans la clé list du dictionnaire weatherData.
En-tête HTTP
Avec l’architecture reseau d’un lycée, le logiciel proxy va filtrer les requêtes, et empêcher de lancer celles-ci depuis un script python. Cela peut constituer une faille de sécurité.
L’en-tête HTTP va comporter une signature du client, et le proxy va distinguer un navigateur d’un IDE python.
On peut vouloir modifier l’en-tête HTTP pour imiter le comportement d’un navigateur.
Paramètre
Valeur par défaut (requests)
Valeur “Navigateur” (à imiter)
User-Agent
python-requests/x.x
Mozilla/5.0 … Chrome/…
Accept
*/*
text/html, …
Accept-Language
(Absent)
fr-FR, fr;q=0.9
Signature TLS
Bibliothèque Python
Moteur Blink/WebKit (Chrome/Firefox)
Voici adaptation du script que l’on peut alors utiliser depuis le lycée.
Comme tout langage, python utilise des instructions. Ce sont :
les affectations, opérations
les definitions de fonctions
l’appel de fonctions
les instructions conditionnelles
les boucles
Les types de base en python
Créer et affecter une valeur
Def: Une variable est un espace mémoire auquel on donne un nom. Une variable a un type, et stocke une valeur. L’affectation se fait avec le symbole =
Variable et type
Def: Un type définit l’ensemble des valeurs possibles pour les données, les relations entre ces données, et les opérations que l’on peut réaliser.
Pour déterminer le type d’une variable, on utilise la fonciton type:
>x=5>type(x)int
Les types de base sont:
nombres entiers: int
nombres à virgule flottante: float
chaine de caracteres: str
les variables logiques booléens: bool (True ou False)
le type rien: None
Les nombres entiers et décimaux
Un entier: C’est un nombre qui n’a pas de point décimal.
Pour les décimaux (les flottants), ceux-ci ont pour rôle d’approcher les nombre réels, mais il est impossible de les représenter EXACTEMENT. Le séparateur est un point plutôt qu’une virgule.
Attention, il est impossible de comparer des flottants entre eux. On préfèrera alors eviter de les utiliser pour des tests logiques d’egalité (==).
Pour les puissance de 10 (notation scientifique): On peut utiliser la notation scientifique e ou E. Le nombre d’Avogadro s’écrit ainsi:
$$6.02E23$$
Pour transformer le type, on utilise les fonctions int, float, str:
type de depart
type d’arrivée
fonction
int
str
str(x)
str
int
int(x)
int
float
float(x)
istr
float
float(x)
Type booléen
Ce sont les valeurs True`` et ``False. Les expressions logiques, dont l’evaluation vaut True ou False utilisent les opérateurs de comparaison (>, >=, <, <=, ==, !=), plus les suivants : and, or, not, in, not in:
Lorsque l’on affecte une expression à une variable, celle-ci est d’abord evaluée avant que la valeur ne soit affectée:
a=10b=20c=a<bandb<100# c'est d'abord l'expression a < b puis True AND b < 100 qui est evaluée (True)# puis c stocke True
Les expressions booléennes sont utilisées pour les structures conditionnelle (if ... elif ... else).
Les chaînes de caractères
Definition: C’est une séquence constituée d’un ou plusieurs caractères, entourés de guillemets simples ou doubles.
Remarque: ne pas confondre le nom d’une variable avec la chaine de caractères:print('a') ≠ print(a)…
a=10print(a)# affiche 10print('a')# affiche .a
On peut réaliser des concatenations sur les chaines avec les opérateurs +, *.
On peut aussi réaliser les opérations de comparaison >, <, ==, !=sur les chaines. Et aussi le test d’appartenance in, not in. Ces opérations retournent un booléen.
comparaison d’ordre: A < B vaut True, Ab < A vaut False.
d’égalité: HA == ha vaut False
ou in jour vaut True
ou not in jour vaut False
Boucles
Boucle non bornée
Definition: ** Une boucle non bornée permet de répéter un élément de code un nombre à priori inconnu de fois.
Pour la boucle non bornée, on définit un variant de boucle au départ, i qui vaut zero. Puis on augmente i d’une unité à chaque itération, jusqu’à ce que sa valeur atteigne 9. Puis la condition i < 10 n’est plus réalisée et le script poursuit après la boucle.
On écrit l’instruction: while <condition>:
Le bloc de code est indenté sous cette première ligne:
while<condition>:instruction1instruction2instructionsuivante# suite du programme
Exemple:
r=4whiler>0:r=r-3print('à la fin du programme, r vaut '+str(r))
Boucle bornée (non traité)
Definition: ** Une boucle bornée permet de répéter un élément de code un nombre fixe de fois.
On rappelle que la différence entre une boucle bornée et non bornée est la definition d’un variant de boucle. Celui-ci varie sur une étendue qui est déclarée au depart.
La fonction range(X) établit une liste de valeurs itérables, que prend le variant i qui est déclaré dans la boucle: i vaut successivement {0, 1, 2, 3, 4, 5, 6, 7, 8, 9}, de 0 à X-1.
Les scripts suivants sont équivalents:
foriinrange(10):passi=0whilei<10:i=i+1
Pour la boucle bornée, i est le variant de boucle, qui évolue à chaque itération de 0 à 9.
Erreurs et bugs
Les erreurs de syntaxe
dues au non-respect des règles d’écriture de Python (parenthèses, :, …)
erreur de definition
dues à l’usage d’un nom qui n’a pas encore été défini (variable ou fonction):
>>> a = a + 1
Traceback (most recent call last):
File "<input>", line 1, in <module>
NameError: name 'a' is not defined
erreurs de type
print(3 + 'cm') génère l’erreur *unsupported operand type(s) for +: ‘int’ and ‘str’
erreurs d’execution
dues à des instructions que l’ordinateur ne sait pas exécuter, comme un division par zero.
Erreurs de logique
n’occasionnent en général pas de message d’erreur, mais provoquent des problèmes inatendus (boucle infinie, autre…)
Pour prévenir des erreurs logiques, il peut être utile d’utiliser des traces dans son programme pour comprendre la cause de l’erreur. On rajoute généralement des sorties print(variable) pour les variables que l’on veut suivre lors de l’execution.
Les fonctions
Def: Une fonction permet d’encapsuler un bloc d’instructions et de lui donnéer un nom.
On peut ensuite exécuter ce bloc en utilsant ce nom. On dit qu’on appelle cette fonction.
Def: Valeur de retour: Une fonction retourne en général une valeur. Après le mot-clé return:
defhello():return'Hi'hello()# 'Hi'
Une fonction peut avoir plusieurs paramètres qui permettent de transmettre des valeurs au bloc d’instructions. A l’interieur de la fonction, ces paramètres sont traités comme des variables, mais locales: Elles n’existent pas à l’exterieur du bloc. (voir plus loin)
Lors de l’appel de la fonction, le nombre d’arguments passés doit correspondre au nombre de paramètres attendus. (sauf si pour les paramètres ayant une valeur par defaut). Il y a alors une affectation: paramètre = argument
defcarre(x):returnx**2carre(5)# 25
Portée des variables
Lorsqu’une fonction utilise des variables, celles-ci sont normalement propres à la fonction et ne sont pas accessibles à l’extérieur de celle-ci. On dit qu’il s’agit de variables locales, par opposition aux variables globales, du programme principal.
Exemple: si on définit une variable a avant la définition de la fonction, celle-ci sera différente du a de la fonction somme:
a=10defsomme(a,b):s=a+breturns>>>somme(1,0)1
Python permet d’affecter à l’intérieur d’une fonction, une variable globale. Pour cela, il faut déclarer la variable comme étant globale au début de la fonction:
a=10defsomme(b):globalas=a+breturns>>>somme(0)10
Modifier une variable globale depuis une fonction s’appelle un effet de bord. C’est considéré comme une mauvaise pratique, mais parfois indispensable.
Modules
Une fonction peut être placée dans un autre fichier. On a alors:
un fichier principal (le programme main)
un ou plusieurs fichiers annexes (modules)
**Def:**Un module apporte des fonctions et des variables et permet une extension du langage.
Le programme principal doit alors faire référence aux modules. L’une des manières est la suivante:
importmodulefrommoduleimport*importmoduleasalias
Exemples:
import du module
appel d’une fonction du module
import math
math.sin(x)
from math import sin
sin(x)
from math import *
sin(x)
import numpy as np
np.arrange(3, 15, 2)
Comment choisir la bonne méthode?
Il est recommandé de ne charger que les fonctions utiles du module, avec: from module import fonction1, fonction2
Si on importe le module entier, on préfera import module pour utiliser la fonction avec la notation pointée module.fonction.
Pour executer l’un des modules depuis le shell python, on peut écrire:
>>>fromprogrammeimport*
Exemple: supposons que le programme suivant soit dans le fichier test.py
# contenu du fichier test.pya=10defsomme(b):s=a+10returns
On execute le programme dans le shell:
>>>fromtestimport*>>>a10>>>somme(0)20
Exercices
Exercices
Questions à reponses courtes
a. Quels sont les 2 types numeriques en Python ?
b. True et False: Quel est leur type?
c. Comment fait-on l’affectation multiple de la valeur 3 à la variable a et 55 à la variable b?
d. Former la chaine “Ring the Bell” à partir de a = "Ring", b = "the"et c = "Bell".
e. Que donne l’expression: 26 // 4 ?
f. Que donne l’expression: 26 % 4 ?
g. Que donne l’expression: ``“4” + “4”` ?
h. Que donne l’expression: str("4") + 4 ?
i. Que donne l’expression `“Sup” * 3 ?
j. Traduire en Python le calcul: $(1,2.10^{-3})**2$
k. Quelle erreur est renvoyée par: "4" + 4?
l. L’instruction suivante: a = a + 1 génère une erreur de type NameError. Pourquoi?
Calcul avec des propositions
a. Que donne l’expresion suivante: 10 > 9 and 3 < 4?
b. Que donne l’expresion suivante: 10 > 9 and 5 < 4?
c. Que donne l’expresion suivante: 10 > 9 or 3 < 4?
d. Que donne l’expresion suivante: True or False?
e. Que donne l’expresion suivante: True and not False?
Variables et opérations
script 1
age=0annee=2001age=age+17annee=annee+age
a. Que vaut année à la fin du script?
b. Que vaut age à la fin du script?
script 2
age=input('Quel est ton age?')nom=nput('Quel est ton nom?')message="ton nom est "+nom+", et tu as "+age+" ans"
a. L’utilisateur du programme repond 21 puis Francois. Qu’est ce qui est affiché à l’écran?
On ajoute la ligne suivante au programme:
annee_de_naissance=2023-age
b. Cela génère une erreur de type. Pourquoi? Comment corriger ce problème?
Instruction conditionnelle
Ecrire l’instruction conditionnelle qui affiche la phrase “il va faire très froid / froid / bon / chaud / très chaud” selon la valeur de la variable t (la température). Vous choisirez les seuils entre chaque niveau de température.
Ecrire une fonction meteo qui retourne “froid / froid / bon / chaud / très chaud” selon le paramètre t. Et écrire le programme qui appelle la fonction pour afficher “il va faire …”.
Boucle non bornée
Multiplication
Compléter le script suivant qui réalise la multiplication de a par b, en n’utilisant que l’opérateur +:
Ecrire un script qui réalise la division de a par b, en n’utilisant que l’opérateur -.
Autres exercices
addition de chaines de caractères
Dans le Bourgeois Gentilhomme, Molière (acte 2 scene 4): le Maitre de Philosophie dit:
On les peut mettre premièrement comme vous avez dit : « Belle Marquise, vos beaux yeux me font mourir d’amour ». Ou bien : « D’amour mourir me font, belle Marquise, vos beaux yeux ». Ou bien : « Vos yeux beaux d’amour me font, belle Marquise, mourir ». Ou bien : « Mourir vos beaux yeux, belle Marquise, d’amour me font ». Ou bien : « Me font vos yeux beaux mourir, belle Marquise, d’amour ».
La leçon d'orthographe.
a. Définir plusieurs variables contenant les morceaux de la phrase “Belle Marquise, …”, de telle sorte que l’on puisse afficher avec la fonction print et l’opérateur + des chaines de caractères, les différentes variantes énoncées. (On ignore la distinction entre majuscule et minuscule).
b. Ecrire l’opération sur ces variables qui donne chacune des phrases.
Nous allons voir 3 options pour réaliser les scripts python turtle. La syntaxe diffère légèrement selon si vous utilisez la calculatrice TI83 CE Premium Python, la tablette Android, ou bien un interpreteur en ligne.
Les 3 programmes proposés permettent de réaliser cette première figure.
TI83 CE Premium Python
La calculatrice doit être à jour. Il faudra ajouter le module CE_turtle pour pouvoir utiliser le module python turtle. Voir notice d’installation
Dans l’App Python: démarrer un nouveau script. Ecrire et rédiger la première ligne: from turtle import *. Quitter le shell et revenir dans l’editeur de programme pour poursuivre l’edition. Voir Notice turtle pour la TI83
télécharger le dossier zip:
tuto_tkinter.zip
* le placer dans vos Documents
Extraire tout
Ouvrir le fichier main.py avec un IDE Python de la suite Winpython
Import des modules
Le module tkinter apporte l’environnement graphique.
Le module PIL permet la gestion des images.
Démarrer votre fichier par:
fromtkinterimport*fromPILimportImage,ImageTk
Créer une fenêtre Tkinter
La fenêtre est un objet de la classe Tk. Pour l’exemple qui suit, on lui donne le nom de fen1.
On créé un objet fenêtre à partir de l’instruction: fen1 = Tk()
La dernière ligne permet d’afficher la fenêtre à l’écran. Il faudra auparavent ajouter les objets esclaves.
if__name__=='__main__':fen1=Tk()# ajouter des objets esclaves à la fenêtre# puis finir par:fen1.mainloop()
Objets esclaves
Ces objets sont à ajouter à fen1, une fois celle-ci créé. Donc après fen1 = Tk()
Canvas
C’est la partie de la fenêtre dans laquelle on dessine.
On commence par créer un objet canvas appelé ici can1: c’est l’instruction can1 = Canvas(fen1, ...arguments...). Les arguments vont permettre de choisir par exemple la largeur en pixel du canvas (width) et sa hauteur (height).
Puis on positionne can1 avec la méthode pack. Sans cette deuxième ligne can1.pack(side=LEFT, padx=5, pady=5), l’objet esclave est créé mais non attaché à la fenêtre (et donc n’apparait pas).
Les boutons vont permettre d’appeler des fonctions lorsque l’on clique dessus.
Par exemple, le bouton 1, bou1 va appeler une fonction de fen1 héritée lors de sa création à partir de la classe Tk. C’est la fonction quit.
Et le bouton 1, bou2, va appeler la fonction replay qu’il vous faudra programmer. Que voudrez vous qu’il se passe lorsque l’on clique sur ce bouton…? Effacer le canvas, dessiner une grille,…?
if__name__=='__main__':...# un boutonbou1=Button(fen1,text='Quitter',command=fen1.quit)bou1.pack(side=BOTTOM)# un autre boutonbou2=Button(fen1,text='(Re)Jouer',command=replay)bou2.pack()
Remarques: en python, il est possible de mettre en argument d’une fonction une autre fonction. C’est ce qui est réalisé ici, avec les fonctions fen1.quit et replay. On appelle ces fonctions sans mettre de parenthèses: on écrit replay et non replay().
Etiquette: Label
On peut écrire un texte dont le contenu sera evolutif, comme un panneau d’affichage dont le contenu est variable:
if__name__=='__main__':...text_affichage=StringVar()txt1=Label(fen1,textvariable=text_affichage,justify=LEFT,font='TkFixedFont')txt1.pack()text_affichage.set("Cliquer sur \n le bouton \n pour demarrer")
Plus tard, dans le programme, il suffira d’écrire text_affichage.set("nouveau \n message") pour afficher un nouveau message, à la même place.
textBox
Equivalent de input mais pour l’environnement tkinter. Il faudra definir le champs de saisie (objet Text), et le bouton pour validation:
if__name__=='__main__':...# Une textBoxtextBox=Text(fen1,height=1,width=15)textBox.pack()# Bouton pour valider la saisiebou3=Button(fen1,text='Valider',command=readtext)bou3.pack()
Il faudra alors programmer la fonction de rappel readtext:
créer un objet image à partir du module tkinter: image_bomb
dessiner l’image dans le canvas à la position 100 * 100
if__name__=='__main__':...# une image de dimension 50 pixels * 50 pixels image=Image.open("images/bomb.png")image=image.resize((50,50),Image.ANTIALIAS)image_bomb=ImageTk.PhotoImage(image)bomb=can1.create_image(100,100,anchor="nw",image=image_bomb)
Plus loin dans le programme, il suffira d’écrire bomb = can1.create_image(200, 200, anchor="nw", image=image_bomb) pour dessiner l’image à la position 200 * 200 par exemple.
Dessiner dans le canvas
Dessiner un carré
On utilise la méthode: .create_rectangle(X0, Y0, X1, Y1)
X, Y sont les coordonnées du coin supérieur gauche du carré.
Il peut y avoir des paramètres optionnels.
Exemple: pour dessiner un carré de côté r dans le canvas:
Ici, la fonction qui sera appelée lorsque l’on clique avec le bouton gauche de la souris dans le canvas est la fonctionclic qu’il faudra programmer.
Lors de l’appel de cette fonction, il ne faut pas ajouter d’agument ni de parenthèses.
On peut par exemple vouloir afficher les coordonnées de la souris lors du clic:
defclic(event):""" Gestion de l'événement clic gauche sur la zone graphique """# MODE JEU# (X,Y) : position du pointeur de la sourisX=event.xY=event.ytext_affichage.set("{}, {}".format(X,Y))
Remarque: la fonction de rappel clic a un paramètre obligatoire, event lors de sa création.
Cliquer sur une image
Pour ajouter un ecouteur de clic sur une image, on procède d’une manière presque identique:
Après avoir placé l’image dans le canvas, on lui associe une fonction de rappel:
Souvent, le jeu utilise un quadrillage sur tout le canvas.
On peut programmer une fonction carre qui dessine un carré de côté r, puis appeler cette fonction lors du dessin initial, dans une autre fonction.
defcarre(r,X,Y,couleur):"""
dessine le contour d'une case colorée
"""can1.create_rectangle(X,Y,X+r,Y+r,outline='black',fill=couleur)
La fonction qui dessine le fond quadrillé utilisera 2 boucles bornées imbriquées. Si chaque carré a pour côté H: L’idée est d’utiliser les dimensions du canvas pour avoir un nombre entier de carrés de côtés H:
famille de jeux: le morpion, puissance 4, echecs, demineur
Exemple 2: dessiner selon le texte saisi
On pourrait dessiner avec un ordre: la fonction de rappel readtext pourrait évaluer les caractères saisis, et, s’il s’agit de:
tete: dessiner la tête du personnage
corps: dessiner le corps
bras: dessiner ses bras
jambes: dessiner ses jambes
famille de jeux: jeu de devinette, jeu de rôle, jeu du pendu
Exemple 3: ajouter une image lors d’un clic
Avec la fonction clic, on peut créer une nouvelle image dans le canvas avec:
defclic(event):""" Gestion de l'événement clic gauche sur la zone graphique """# MODE JEU# (X,Y) : position du pointeur de la sourisX=event.xY=event.ybomb=can1.create_image(X,Y,anchor="nw",image=image_bomb)
Le mieux, serait d’aligner l’image sur la grille de fond lorsque l’on clique dans l’une des cases du quadrillage.
Si les carrés ont pour côté H: Il faudra que X et Y soient multiples de H.
Utiliser la division entière:
X = (X // H) * H
et Y = (Y // H) * H
famille de jeux: demineur, puissance 4, morpion
Tkinter demineur
Canvas et Tkinter
Principe
Le module Tkinter permet de dessiner dans la fenêtre en ajoutant un objet Canvas. Les fonctions de dessin permettent de tracer des figures, afficher une image… Les éléments sont repérés par leur coordonnées (x,y). Le point (0,0) se situant en haut à gauche.
On verra dans une autre seance que le canvas peut aussi relever la position de la souris lors d’un clic. Et que l’on peut ainsi programmer des jeux.
But de la séance
Vous allez poursuivre votre appentissage des algorithmes sur les listes, en positionnant les images bombes sur une grille du canvas.
canvas.py: le fichier principal qui contient les fonctions de dessin. Ce sera ce fichier qui faudra executer pour afficher la fenêtre graphique.
utils.py: C’est le fichier qui contient les fonctions de calcul des positions des bombes. Au depart, ce fichier ne contient que la fonction position_bombes. Cette fonction génère une liste de listes adaptée à la grille $L*h$:
chaque sous-liste positionne les bombes d’une même ligne (L cases)
il y a autant de sous-listes que le nombre de cases en hauteur (h lignes)
une valeur 1 dans la sous-liste positionne une bombe.
une valeur 0 signifie case vide
Vous devrez modifier le contenu de la fonction position_bombes pour réaliser les grilles proposées.
Pour executer le programme, ouvrir canvas.py avec un IDE python, et Executer le module (F5: Run module)
Que génère la fonction position_bombes?
Pour tester la fonction, vous pouvez executer le module utils.py, puis appeler dans le shell la fonction avec des arguments choisis.
Ouvrir le ficher utils.py avec votre IDE python. Puis Executer le module. Dans le shell, faire:
>>>help(position_bombes)# retourne les informations sur la fonction# Pour sortir de la fenêtre de l’aide, appuyer sur la touche q>>>position_bombes(6,6)# retourne la liste Bombes générée par la fonction
Les grilles à réaliser
Il vous faudra modifier la fonction position_bombes pour realiser chacune de ces grilles.
defposition_bombes(L,h):"""
grille pleine
:param L: nombre de cases horizontales
:param h: nombre de cases verticales
:return Bombes: matrice de dimension L*h
retourne une liste de binaires avec la position des bombes
exemple:
--------
>>> position_bombes(
"""
grille 1
defposition_bombes(L,h):"""
ligne horizontale de bombes
:param L: nombre de cases horizontales
:param h: nombre de cases verticales
:return Bombes: matrice de dimension L*h
retourne une liste de binaires avec la position des bombes
exemple:
--------
>>> position_bombes(
"""
grille 2
defposition_bombes(L,h):"""
Premiere ligne verticale
:param L: nombre de cases horizontales
:param h: nombre de cases verticales
:return Bombes: matrice de dimension L*h
retourne une liste de binaires avec la position des bombes
exemple:
--------
>>> position_bombes(
"""
grille 3
defposition_bombes(L,h):"""
diagonale vers le bas a droite
:param L: nombre de cases horizontales
:param h: nombre de cases verticales
:return Bombes: matrice de dimension L*h
retourne une liste de binaires avec la position des bombes
exemple:
--------
>>> position_bombes(
"""
grille 4
defposition_bombes(L,h):"""
position aléatoire de bombes
:param L: nombre de cases horizontales
:param h: nombre de cases verticales
:return Bombes: matrice de dimension L*h
retourne une liste de binaires avec la position des bombes
exemple:
--------
>>> position_bombes(
"""
grille 5
Aide: on pourra utiliser la fonction randint(0,1) du module random
Spécifier la fonction et programmer des tests
Prototypage
Dans chaque cas, compléter le prototypage de la fonction pour:
spécifier ce qu’elle doit faire (début du prototypage)
préciser ce qui est attendu lorsqu’elle est executée avec certaines valeurs choisies pour arguments (fin du prototypage). Ajouter par exemple (compléter):
Et pour réaliser les tests automatiques, il faudra executer le fichier utils.py: Depuis le shell, faire:
>>>pythonutils.py
Remarque: la sortie de la fonction doit suivre le guide de style python, sinon des erreurs peuvent être générées (absence d’espaces,…). Il s’agit de PEP8 sur https://python.org.
IHM python Cours
Interface Homme-Machine en Python avec Pygame
Durée : 1 heure Objectif : Comprendre les bases des interfaces graphiques et du paradigme événementiel pour préparer la création d’un jeu type escape game/RPG
Introduction aux Interfaces Homme-Machine (lecture 10 min)
Qu’est-ce qu’une Interface Homme-Machine (IHM) ?
Une Interface Homme-Machine est le moyen de communication entre un utilisateur et un programme informatique. C’est tout ce qui permet à l’utilisateur d’interagir avec le logiciel et de recevoir des informations en retour.
Exemples du quotidien :
Les applications sur smartphone (boutons, gestes tactiles)
Les sites web (menus, formulaires, boutons)
Les jeux vidéo (interfaces de jeu, menus)
Les logiciels de bureautique (barres d’outils, fenêtres)
Les deux grands types d’interfaces
CLI - Command Line Interface (Interface en ligne de commande)
L’utilisateur tape des commandes textuelles
Le programme répond avec du texte
Exemple : le terminal, les programmes Python simples avec input()
# Exemple CLI classiquenom=input("Quel est votre nom ? ")print(f"Bonjour {nom} !")
Avantages : Simple à programmer, précis, rapide pour les utilisateurs expérimentés Inconvénients : Peu intuitif, courbe d’apprentissage élevée
GUI - Graphical User Interface (Interface graphique)
L’utilisateur interagit avec des éléments visuels (boutons, images, icônes)
Le programme répond visuellement
Exemple : les jeux vidéo, les applications modernes
Avantages : Intuitif, accessible, visuellement attractif Inconvénients : Plus complexe à programmer
Le paradigme événementiel (lecture 15 min)
Du séquentiel à l’événementiel
Programmation séquentielle (ce que vous connaissez)
Le programme s’exécute ligne par ligne, de haut en bas, de manière prévisible.
# Exemple séquentielprint("Début du programme")x=5y=10resultat=x+yprint(f"Résultat : {resultat}")print("Fin du programme")
Le programme se termine après la dernière ligne.
Programmation événementielle (nouveau paradigme)
Le programme reste en attente et réagit aux actions de l’utilisateur.
Le programme ne se termine que lorsque l’utilisateur décide de le fermer.
Les événements
Un événement est une action effectuée par l’utilisateur (ou par le système) que le programme peut détecter et traiter.
Types d’événements courants :
MOUSEBUTTONDOWN : L’utilisateur clique avec la souris
MOUSEBUTTONUP : L’utilisateur relâche le bouton de la souris
MOUSEMOTION : L’utilisateur déplace la souris
KEYDOWN : L’utilisateur appuie sur une touche du clavier
KEYUP : L’utilisateur relâche une touche
QUIT : L’utilisateur ferme la fenêtre
Schéma de la boucle événementielle
┌─────────────────────────────────┐
│ Initialisation du programme │
└────────────┬────────────────────┘
│
▼
┌────────────────────────────────┐
│ BOUCLE PRINCIPALE (infinie) │◄───┐
├────────────────────────────────┤ │
│ 1. Récupérer les événements │ │
│ 2. Traiter chaque événement │ │
│ 3. Mettre à jour la logique │ │
│ 4. Dessiner à l'écran │ │
│ 5. Rafraîchir l'affichage │────┘
└────────────┬───────────────────┘
│
▼ (si événement QUIT)
┌────────────────────────────────┐
│ Fermeture propre │
└────────────────────────────────┘
Introduction à Pygame (lecture 20 min)
Pourquoi Pygame ?
Pygame est une bibliothèque Python spécialement conçue pour créer des jeux 2D et des applications graphiques interactives.
Avantages :
Facile à apprendre pour les débutants
Gestion simplifiée des graphismes, sons et événements
Grande communauté et nombreux tutoriels
Idéal pour des jeux 2D, prototypes et projets éducatifs
Installation :
pip install pygame
Structure minimale d’un programme Pygame
Voici le squelette de base que vous utiliserez pour tous vos projets Pygame :
importpygame# ============================================# INITIALISATION# ============================================pygame.init()# Création de la fenêtreLARGEUR=600HAUTEUR=600screen=pygame.display.set_mode((LARGEUR,HAUTEUR))pygame.display.set_caption("Mon premier programme Pygame")# Horloge pour contrôler les FPS (images par seconde)clock=pygame.time.Clock()# Variable de contrôle de la bouclerunning=True# ============================================# BOUCLE PRINCIPALE# ============================================whilerunning:# 1. GESTION DES ÉVÉNEMENTSforeventinpygame.event.get():ifevent.type==pygame.QUIT:running=False# 2. LOGIQUE DU JEU: # (mise à jour des positions, calculs, etc.)# 3. AFFICHAGE: screen.fill((0,0,0))# Efface l'écran avec du noir# Dessiner vos éléments icipygame.display.flip()# Met à jour l'affichage# 4. CONTRÔLE DU FRAMERATEclock.tick(60)# 60 images par seconde# ============================================# FERMETURE PROPRE# ============================================pygame.quit()
Explication détaillée des éléments clés
Initialisation de Pygame
pygame.init()
Cette ligne initialise tous les modules de Pygame. Elle doit toujours être appelée au début.
Création de la fenêtre
screen=pygame.display.set_mode((LARGEUR,HAUTEUR))
Crée une fenêtre de dimensions LARGEUR × HAUTEUR pixels. L’objet screen représente la surface d’affichage principale.
exemple: pygame.display.set_mode((600, 600))
L’horloge
clock=pygame.time.Clock()# ... plus tard dans la boucleclock.tick(60)
L’horloge contrôle la vitesse du jeu. clock.tick(60) limite le programme à 60 images par seconde (FPS), rendant le jeu fluide et cohérent sur différentes machines.
La boucle de jeu
whilerunning:
C’est le cœur du programme. Tant que running est True, le programme continue. Cette boucle s’exécute environ 60 fois par seconde.
pygame.event.get() récupère tous les événements qui se sont produits depuis la dernière itération. On parcourt cette liste et on réagit selon le type d’événement.
D’autres evenements utiles:
# retourne True si le bouton souris est appuyéevent.type==pygame.MOUSEBUTTONDOWN
# True si le bouton est relachéevent.type==pygame.MOUSEBUTTONUP
Remplissage de l’écran
screen.fill((0,0,0))
Efface l’écran en le remplissant d’une couleur. Les couleurs en Pygame sont des tuples RGB : (Rouge, Vert, Bleu) avec des valeurs de 0 à 255.
Exemples :
(0, 0, 0) = noir
(255, 255, 255) = blanc
(255, 0, 0) = rouge
(0, 255, 0) = vert
(0, 0, 255) = bleu
Rafraîchissement de l’affichage
pygame.display.flip()
Met à jour tout l’écran avec ce qui a été dessiné. Sans cette ligne, rien ne s’affichera !
Exemple complet n°1: Fenêtre avec changement de couleur au clic
importpygameimportrandompygame.init()screen=pygame.display.set_mode((800,600))pygame.display.set_caption("Changer la couleur au clic")clock=pygame.time.Clock()# Couleur de fond initialecouleur_fond=(50,50,100)running=Truewhilerunning:foreventinpygame.event.get():ifevent.type==pygame.QUIT:running=False# Détecter un clic de sourisifevent.type==pygame.MOUSEBUTTONDOWN:# Changer la couleur aléatoirementcouleur_fond=(random.randint(0,255),random.randint(0,255),random.randint(0,255))# Remplir l'écran avec la couleur actuellescreen.fill(couleur_fond)pygame.display.flip()clock.tick(60)pygame.quit()
Exercice mental : Que se passe-t-il si vous cliquez plusieurs fois?
Éléments pour votre projet (lecture 10 min)
Pour créer votre escape game/RPG, vous aurez besoin de maîtriser ces éléments :
Afficher une image de fond
# Chargement d'une imageimage_fond=pygame.image.load("fond_salle.png")# Dans la boucle, affichage de l'imagescreen.blit(image_fond,(0,0))# (0, 0) = position en haut à gauche
Note importante : Le système de coordonnées dans Pygame :
(0, 0) ──────► X (largeur)
│
│
│
▼
Y (hauteur)
Le point (0, 0) est en haut à gauche de l’écran !
Afficher une image à une certaine position
placer une figure rectangle
La fonction pygame.draw.rect(screen, color, (x, y, width, height)) dessine un rectangle. (x, y, width, height) est un tuple Python.
x et y sont les coordonnées du coin supérieur gauche. width et height sont la largeur et la hauteur du rectangle:
# Dans la boucle d'événementsifevent.type==pygame.MOUSEBUTTONDOWN:x,y=event.pos# Position du clic# Vérifier si le clic est dans une zone rectangulaire# Zone de l'objet : x entre 100 et 200, y entre 150 et 250if100<=x<=200and150<=y<=250:print("Vous avez cliqué sur l'objet !")
relacher:
# Dans la boucle d'événementsifevent.type==pygame.MOUSEBUTTONUP:x,y=event.pos# Position du clic# Vérifier si le clic est dans une zone rectangulaire# Zone de l'objet : x entre 100 et 200, y entre 150 et 250if100<=x<=200and150<=y<=250:print("Vous avez relaché le bouton !")
Exemple complet n°4
importpygameRED=(255,0,0)BLUE=(0,0,255)pygame.init()h,w=400,400screen=pygame.display.set_mode((w,h))pygame.draw.rect(screen,RED,(170,140,60,120))stop=Falsewhilenotstop:foreventinpygame.event.get():ifevent.type==pygame.QUIT:stop=Trueifevent.type==pygame.MOUSEBUTTONDOWN:x,y=event.posif170<=x<=230and140<=y<=260:print("Vous avez cliqué sur l'objet !")ifevent.type==pygame.MOUSEBUTTONUP:x,y=event.posif170<=x<=230and140<=y<=260:print("Vous avez relaché le bouton !")pygame.display.flip()pygame.quit()
Exercice 1: Créer un programme complet qui permet de changer la couleur de la porte lorsque l’on clique sur celle-ci (et que l’on maintient appuyé), mais qui remet la première couleur lorsque l’on relâche le bouton:
Exercice 2: Créer un programme qui permet de changer la couleur de la porte lorsque l’on clique sur celle-ci. Il faudra à nouveau cliquer sur la porte pour retrouver la couleur d’origine.
Detecter un clic sur un objet
Méthode : Utilisez pygame.Rect pour créer un calque rectangle:
# Définir un rectangle pour l'objetobjet_rect=pygame.Rect(100,150,100,100)# x, y, largeur, hauteur# Dans la boucle d'événementsifevent.type==pygame.MOUSEBUTTONDOWN:ifobjet_rect.collidepoint(event.pos):print("Objet cliqué !")
Utiliser ce calque sur une image
Il faut appliquer le calque sur l’image, qui aura les mêmes dimensions que celle-ci:
# charger l'imagedoor=pygame.image.load("datas/images/door1.png")# creation d'une surface rectangle # que l'on nomme rect# de meme dimension que l'image doorrect=door.get_rect()# Position de rect dans la fenetre graphique (centré)rect.center=w//2,h//2# Dessiner l'objet à la même position que le calquescreen.blit(door,rect)
Ce calque est alors cliquable:
ifevent.type==pygame.MOUSEBUTTONDOWN:ifrect.collidepoint(event.pos):print("l'objet a ete cliqué")
Exemple complet n°5:
importpygamepygame.init()door=pygame.image.load("datas/images/door1.png")h,w=400,400screen=pygame.display.set_mode((w,h))rect=door.get_rect()rect.center=w//2,h//2stop=Falsewhilenotstop:foreventinpygame.event.get():ifevent.type==pygame.QUIT:stop=Trueelifevent.type==pygame.MOUSEBUTTONDOWN:ifrect.collidepoint(event.pos):print('on tape à la porte')screen.fill(0)# On efface tout l'écranscreen.blit(door,rect)pygame.display.flip()pygame.quit()
Exercice 1: On dispose de 2 images d’une même porte, aux contours différents. Créer un programme complet qui permet de changer l’image de la porte lorsque l’on clique sur celle-ci (et que l’on maintient appuyé), mais qui remet la première image lorsque l’on relâche le bouton:
Exercice 2: Créer un programme qui permet de changer l’image de la porte lorsque l’on clique sur celle-ci. Il faudra à nouveau cliquer sur la porte pour retrouver l’image d’origine.
Afficher du texte
Première étape: utiliser le module font. On créé un objet pygame.font, pour lequel on choisit une police de caractères (par defaut, laisser None) et une taille pour cette police:
my_font=pygame.font.SysFont('Comic Sans MS',30)
il faut créer une surface sur laquelle on écrit, à l’aide de la fonction render:
L’anticrénelage ou anti-aliasing, ou lissage des obliques ou encore lissage de police, est une méthode permettant d’éviter le crénelage.
Troisième étape: Afficher et positionner la surface avec la fonction blit:
screen.blit(texte_surface,(0,0))# Position du texte # en haut à gauche
au final:
screen.fill(255,255,255)font=pygame.font.Font(None,36)# None = police par défaut, 36 = tailletexte="Bienvenue dans la salle mystérieuse"texte_surface=font.render(texte,True,(0,0,0))# True = antialiasingscreen.blit(texte_surface,(50,500))# Position du texte
Exemple complet n°6:
importpygamepygame.init()h,w=400,400screen=pygame.display.set_mode((w,h))screen.fill(255,255,255)font=pygame.font.Font(None,36)texte="Bienvenue dans la salle mystérieuse"texte_surface=font.render(texte,True,(0,0,0))screen.blit(texte_surface,(50,500))stop=Falsewhilenotstop:foreventinpygame.event.get():ifevent.type==pygame.QUIT:stop=Truepygame.display.flip()pygame.quit()
Remarques:
Chaque fois que le texte change, il faudra créer une nouvelle surface à placer sur l’ancienne.
Pour changer de ligne, on ne pourra pas utiliser le symbole “\n”. Il faudra créer une nouvelle surface pour chaque ligne, et la positionner de manière correcte.
Exercice: Ecrire un programme qui affiche les 2 lignes comme ci-dessus.
Detecter l’appui sur une touche du clavier
Pour detecter l’appui sur la touche "h" du clavier, on utilisera la séquence d’instruction suivantes:
D’abord : affichez juste la fenêtre et l’image de fond
Ensuite : ajoutez la détection de clic sur une zone
Puis : ajoutez l’affichage de texte
Enfin : ajoutez les boutons et la logique du jeu
4. Utilisez des commentaires et des constantes
# ConstantesLARGEUR=800HAUTEUR=600COULEUR_FOND=(0,0,0)FPS=60# États du jeuETAT_DEBUT=0ETAT_JEU=1ETAT_VICTOIRE=2
Structure de base pour votre TP
importpygamepygame.init()screen=pygame.display.set_mode((800,600))clock=pygame.time.Clock()# Chargement des ressourcesfond=pygame.image.load("salle.png")font=pygame.font.Font(None,28)# Définition des objets interactifsobjets=[# À compléter]# Variables de jeumessage_actuel="Explorez la salle..."inventaire=[]running=Truewhilerunning:# Gestion des événementsforeventinpygame.event.get():ifevent.type==pygame.QUIT:running=Falseifevent.type==pygame.MOUSEBUTTONDOWN:# Vérifier les clics sur les objets# Vérifier les clics sur les boutonspass# Affichagescreen.blit(fond,(0,0))# Afficher les boutons# Afficher le messagetexte=font.render(message_actuel,True,(255,255,255))screen.blit(texte,(50,550))pygame.display.flip()clock.tick(60)pygame.quit()quit()
Récapitulatif des concepts clés
✅ IHM : Moyen de communication entre l’utilisateur et le programme
✅ Paradigme événementiel : Le programme attend et réagit aux actions
✅ Boucle de jeu : Cœur du programme, s’exécute en continu
✅ Événements : Actions détectables (clics, touches, etc.)
✅ Pygame : Bibliothèque pour créer des jeux 2D en Python
✅ Structure : Init → Boucle (événements → logique → affichage) → Quit
Les dictionnaires python et leur application pour le projet Escape Game: Lien
dictionnaires pour inventaire
Les dictionnaires Python pour gérer un escape game
Durée : 1 heure Prérequis : Connaître les listes Python Objectif : Découvrir les dictionnaires et comprendre pourquoi ils sont essentiels pour gérer les objets et états d’un jeu
1. Rappel : Les listes, ce que vous connaissez déjà (10 min)
Structure des listes
Une liste est une collection ordonnée d’éléments, accessibles par leur position (index).
# Liste de prénomsprenoms=["Alice","Bob","Charlie"]# Accès par index (position)print(prenoms[0])# Affiche : Aliceprint(prenoms[1])# Affiche : Bobprint(prenoms[2])# Affiche : Charlie
Utiliser les listes pour un jeu : première tentative
Imaginons qu’on veuille gérer un objet de notre escape game avec une liste :
# Un objet "clé" représenté par une listecle=["clé dorée",150,200,False,"Une petite clé qui brille"]# [0] nom [1] x [2] y [3] ramassée [4] description# Accès aux informationsprint(cle[0])# nomprint(cle[1])# position xprint(cle[3])# est-elle ramassée ?
Le problème avec les listes
❌ Difficile à lire : Que représente cle[3] ? Il faut se souvenir de l’ordre
❌ Difficile à maintenir : Si on ajoute une propriété, tous les indices changent
❌ Erreurs faciles : Confondre l’ordre des éléments
❌ Code cryptique : if objet[3] == False: ne dit rien sur ce qu’on vérifie
Exercice mental : Si on a 10 objets différents avec des propriétés différentes, comment s’en sortir avec des listes ?
2. Introduction aux dictionnaires (15 min)
Qu’est-ce qu’un dictionnaire ?
Un dictionnaire est une collection d’éléments accessibles par leur nom (clé) plutôt que par leur position.
Analogie : Un dictionnaire papier
Dans un dictionnaire français, on cherche un mot (la clé) pour obtenir sa définition (la valeur)
On ne dit pas “donne-moi le 1547ème mot”, mais “donne-moi la définition de ’escape'”
Syntaxe de base
# Création d'un dictionnairepersonne={"nom":"Alice","age":25,"ville":"Paris"}# Accès par clé (beaucoup plus clair !)print(personne["nom"])# Affiche : Aliceprint(personne["age"])# Affiche : 25print(personne["ville"])# Affiche : Paris
Les clés sont généralement des chaînes de caractères (entre guillemets)
Les valeurs peuvent être de n’importe quel type : nombres, chaînes, booléens, listes, ou même d’autres dictionnaires !
Comparaison liste vs dictionnaire
# AVEC UNE LISTE (difficile à lire)cle_liste=["clé dorée",150,200,False,"Une petite clé qui brille"]nom=cle_liste[0]est_ramassee=cle_liste[3]# AVEC UN DICTIONNAIRE (clair et explicite)cle_dict={"nom":"clé dorée","x":150,"y":200,"ramassee":False,"description":"Une petite clé qui brille"}nom=cle_dict["nom"]est_ramassee=cle_dict["ramassee"]
joueur["vie"]=80# La vie passe à 80joueur["niveau"]=2# Le niveau passe à 2
Ajouter une nouvelle paire clé-valeur
joueur["score"]=1500# Ajoute une nouvelle clé "score"
Vérifier si une clé existe
if"vie"injoueur:print("Le joueur a des points de vie")if"magie"injoueur:print("Le joueur a de la magie")else:print("Pas de magie")# Ceci sera affiché
Supprimer une paire clé-valeur
deljoueur["score"]# Supprime la clé "score"
Obtenir une valeur avec une valeur par défaut
# Si la clé n'existe pas, retourne une valeur par défautmagie=joueur.get("magie",0)# Retourne 0 si "magie" n'existe pas
3. Les dictionnaires pour l’escape game (20 min)
3.1. Représenter un objet du jeu
Au lieu d’utiliser des listes compliquées, utilisons des dictionnaires pour chaque objet :
porte={"nom":"porte","x":300,"y":200,"largeur":150,"hauteur":300,"verrouille":True,"description":"Une lourde porte en bois","message_verrouille":"La porte est fermée à clé","message_ouvert":"Vous ouvrez la porte et sortez. Victoire !"}cle={"nom":"clé","x":100,"y":400,"largeur":30,"hauteur":15,"ramassee":False,"description":"Une petite clé dorée","dans_inventaire":False}tableau={"nom":"tableau","x":450,"y":150,"largeur":200,"hauteur":150,"examine":False,"description":"Un tableau représentant un paysage","description_detaillee":"En examinant de plus près, vous voyez un code : 1234"}
Avantages :
✅ Chaque objet peut avoir des propriétés différentes
✅ Le code est auto-documenté (on comprend ce que fait objet["verrouille"])
✅ Facile d’ajouter de nouvelles propriétés
✅ Pas de confusion sur l’ordre des éléments
3.2. Gérer une collection d’objets
On peut mettre tous les objets dans une liste :
objets=[{"nom":"porte","x":300,"y":200,"largeur":150,"hauteur":300,"verrouille":True,"description":"Une lourde porte en bois"},{"nom":"clé","x":100,"y":400,"largeur":30,"hauteur":15,"ramassee":False,"description":"Une petite clé dorée"},{"nom":"coffre","x":550,"y":350,"largeur":100,"hauteur":80,"ouvert":False,"description":"Un vieux coffre poussiéreux"}]
3.3. Parcourir et utiliser les objets
# Afficher tous les objetsforobjetinobjets:print(f"Objet : {objet['nom']} à la position ({objet['x']}, {objet['y']})")# Trouver un objet par son nomdeftrouver_objet(nom_objet):forobjetinobjets:ifobjet["nom"]==nom_objet:returnobjetreturnNone# Utilisationporte=trouver_objet("porte")ifporte["verrouille"]:print("La porte est verrouillée")
3.4. Détecter un clic sur un objet
defverifier_clic_objet(x_souris,y_souris):"""Vérifie si le clic touche un objet"""forobjetinobjets:# Vérifier si le clic est dans les limites de l'objetif(objet["x"]<=x_souris<=objet["x"]+objet["largeur"]andobjet["y"]<=y_souris<=objet["y"]+objet["hauteur"]):returnobjetreturnNone# Dans la boucle d'événementsifevent.type==pygame.MOUSEBUTTONDOWN:x,y=event.posobjet_clique=verifier_clic_objet(x,y)ifobjet_clique:print(f"Vous avez cliqué sur : {objet_clique['nom']}")print(objet_clique["description"])
3.5. Gérer l’inventaire
# L'inventaire est une liste de dictionnairesinventaire=[]deframasser_objet(objet):"""Ajoute un objet à l'inventaire"""ifnotobjet.get("ramassee",False):objet["ramassee"]=Trueinventaire.append(objet)returnf"Vous ramassez : {objet['nom']}"else:return"Cet objet a déjà été ramassé"defafficher_inventaire():"""Affiche le contenu de l'inventaire"""iflen(inventaire)==0:print("Votre inventaire est vide")else:print("Inventaire :")forobjetininventaire:print(f" - {objet['nom']}")defobjet_dans_inventaire(nom_objet):"""Vérifie si un objet est dans l'inventaire"""forobjetininventaire:ifobjet["nom"]==nom_objet:returnTruereturnFalse
3.6. Gérer les interactions entre objets
defutiliser_cle_sur_porte():"""Tente d'ouvrir la porte avec la clé"""porte=trouver_objet("porte")ifobjet_dans_inventaire("clé"):ifporte["verrouille"]:porte["verrouille"]=Falsereturn"Vous utilisez la clé. La porte s'ouvre !"else:return"La porte est déjà ouverte"else:return"Vous n'avez pas de clé"defexaminer_objet(objet):"""Examine un objet en détail"""ifobjet["nom"]=="tableau"andnotobjet.get("examine",False):objet["examine"]=Truereturnobjet.get("description_detaillee",objet["description"])else:returnobjet["description"]
4. Exemple complet : Mini escape game avec dictionnaires (10 min)
Voici un exemple fonctionnel simplifié qui montre comment tout s’assemble :
importpygamepygame.init()screen=pygame.display.set_mode((800,600))clock=pygame.time.Clock()font=pygame.font.Font(None,28)# Définition des objets avec des dictionnairesobjets=[{"nom":"clé","x":100,"y":400,"largeur":40,"hauteur":20,"couleur":(255,215,0),# Doré"ramassee":False,"description":"Une clé dorée"},{"nom":"porte","x":650,"y":200,"largeur":100,"hauteur":200,"couleur":(139,69,19),# Marron"verrouille":True,"description":"Une porte en bois"}]# État du jeuinventaire=[]message="Trouvez la clé et ouvrez la porte !"victoire=Falserunning=Truewhilerunning:foreventinpygame.event.get():ifevent.type==pygame.QUIT:running=Falseifevent.type==pygame.MOUSEBUTTONDOWNandnotvictoire:x_souris,y_souris=event.pos# Vérifier les clics sur les objetsforobjetinobjets:if(objet["x"]<=x_souris<=objet["x"]+objet["largeur"]andobjet["y"]<=y_souris<=objet["y"]+objet["hauteur"]):# Clic sur la cléifobjet["nom"]=="clé"andnotobjet["ramassee"]:objet["ramassee"]=Trueinventaire.append(objet)message="Vous ramassez la clé !"# Clic sur la porteelifobjet["nom"]=="porte":# Vérifier si on a la cléa_la_cle=any(obj["nom"]=="clé"forobjininventaire)ifa_la_cleandobjet["verrouille"]:objet["verrouille"]=Falsemessage="Vous ouvrez la porte ! VICTOIRE !"victoire=Trueelifobjet["verrouille"]:message="La porte est verrouillée. Il faut une clé."else:message="La porte est déjà ouverte !"# Affichagescreen.fill((50,50,50))# Fond gris# Dessiner les objetsforobjetinobjets:# Ne pas dessiner la clé si elle est ramasséeifobjet["nom"]=="clé"andobjet["ramassee"]:continuepygame.draw.rect(screen,objet["couleur"],(objet["x"],objet["y"],objet["largeur"],objet["hauteur"]))# Afficher le messagetexte=font.render(message,True,(255,255,255))screen.blit(texte,(50,550))# Afficher l'inventaireinv_text="Inventaire : "+", ".join([obj["nom"]forobjininventaire])iflen(inventaire)==0:inv_text="Inventaire : vide"inv_surface=font.render(inv_text,True,(200,200,200))screen.blit(inv_surface,(50,20))pygame.display.flip()clock.tick(60)pygame.quit()
Ce que fait ce programme :
Définit une clé et une porte comme dictionnaires
Permet de cliquer sur la clé pour la ramasser
La clé disparaît et va dans l’inventaire
On peut cliquer sur la porte pour tenter de l’ouvrir
La porte s’ouvre seulement si on a la clé
5. Dictionnaires avancés pour le jeu (10 min)
5.1. Dictionnaires imbriqués
On peut mettre des dictionnaires dans des dictionnaires :
objet_complexe={"nom":"coffre","position":{"x":100,"y":200},"dimensions":{"largeur":80,"hauteur":60},"contenu":{"or":50,"gemmes":3,"objet_special":"amulette"},"ouvert":False}# Accès aux valeurs imbriquéesprint(objet_complexe["position"]["x"])# 100print(objet_complexe["contenu"]["or"])# 50
5.2. État global du jeu
Un dictionnaire peut représenter l’état complet du jeu :
etat_jeu={"niveau_actuel":1,"temps_ecoule":0,"enigmes_resolues":["enigme1","enigme3"],"inventaire":[],"score":1500,"indices_trouves":{"code_coffre":True,"message_secret":False},"pieces_visitees":["salon","cuisine"],"drapeaux":{"porte_ouverte":False,"alarme_declenchee":False,"a_parle_au_gardien":True}}# Vérifications facilesif"code_coffre"inetat_jeu["indices_trouves"]:print("Vous connaissez le code du coffre")ifetat_jeu["drapeaux"]["a_parle_au_gardien"]:print("Le gardien vous a donné un indice")
5.3. Actions et interactions
On peut même stocker des fonctions ou des messages dans les dictionnaires :
objets_interactifs=[{"nom":"levier","x":300,"y":250,"actif":False,"description_initial":"Un levier rouillé","description_active":"Le levier a été activé. Un passage secret s'ouvre.","action":"ouvrir_passage"},{"nom":"livre","x":150,"y":180,"lu":False,"description":"Un vieux grimoire","texte":"Les pages révèlent : 'Le code est 4-2-7-9'","action":"donner_indice"}]definteragir_avec_objet(objet):"""Gère l'interaction avec un objet selon son type d'action"""ifobjet["action"]=="ouvrir_passage":objet["actif"]=Truereturnobjet["description_active"]elifobjet["action"]=="donner_indice":ifnotobjet["lu"]:objet["lu"]=Truereturnobjet["texte"]else:return"Vous avez déjà lu ce livre"returnobjet["description"]
5.4. Système de quêtes
quetes=[{"id":"trouver_cle","titre":"Trouver la clé","description":"Cherchez la clé pour ouvrir la porte","terminee":False,"objectifs":{"cle_trouvee":False}},{"id":"resoudre_enigme","titre":"Résoudre l'énigme du tableau","description":"Déchiffrez le message caché dans le tableau","terminee":False,"objectifs":{"tableau_examine":False,"code_trouve":False}}]defverifier_quetes():"""Vérifie si les quêtes sont terminées"""forqueteinquetes:ifnotquete["terminee"]:# Vérifier si tous les objectifs sont remplistous_objectifs=all(quete["objectifs"].values())iftous_objectifs:quete["terminee"]=Truereturnf"Quête terminée : {quete['titre']}"returnNone
6. Comparaison finale et bonnes pratiques (5 min)
Pourquoi les dictionnaires sont parfaits pour les jeux
Critère
Listes
Dictionnaires
Lisibilité
❌ objet[3]
✅ objet["verrouille"]
Flexibilité
❌ Ordre fixe
✅ Propriétés variables
Maintenance
❌ Changer l’ordre casse tout
✅ Ajouter/retirer facilement
Clarté du code
❌ Besoin de commentaires
✅ Auto-documenté
Gestion d’objets complexes
❌ Très difficile
✅ Naturel
Bonnes pratiques avec les dictionnaires
✅ Utilisez des noms de clés descriptifs
# Bienjoueur={"points_de_vie":100,"niveau":5}# Moins bienjoueur={"pv":100,"niv":5}
✅ Soyez cohérents dans la structure
# Tous les objets ont les mêmes clés de baseobjet1={"nom":"...","x":0,"y":0,"description":"..."}objet2={"nom":"...","x":0,"y":0,"description":"..."}
✅ Utilisez .get() pour éviter les erreurs
# Risqué - erreur si la clé n'existe pasvie=joueur["vie"]# Sûr - retourne 100 par défautvie=joueur.get("vie",100)
✅ Documentez la structure de vos dictionnaires
# Structure d'un objet du jeu :# {# "nom": str, # Nom de l'objet# "x": int, # Position X# "y": int, # Position Y# "ramassable": bool, # Peut-on le ramasser ?# "description": str # Description affichée# }
Quand utiliser listes vs dictionnaires ?
Utilisez une liste quand :
L’ordre est important
Vous avez une série d’éléments similaires et simples
Exemple : scores = [100, 95, 87, 82]
Utilisez un dictionnaire quand :
Vous avez des propriétés nommées
Vous voulez accéder aux données par leur signification
Vous gérez des objets complexes
Exemple : joueur = {"nom": "Alice", "score": 100, "niveau": 3}
Récapitulatif
🎯 Les dictionnaires permettent d’accéder aux données par nom (clé) plutôt que par position
🎯 Syntaxe : {"clé": valeur, "clé2": valeur2}
🎯 Parfaits pour : Représenter des objets de jeu avec de multiples propriétés
Créez 3 dictionnaires représentant des objets pour votre escape game. Chaque objet doit avoir au minimum : nom, position (x, y), dimensions, et une description.
Exercice 2 : Fonction de recherche
Écrivez une fonction trouver_objet_par_nom(nom, liste_objets) qui cherche un objet dans une liste de dictionnaires et le retourne.
Exercice 3 : Système d’inventaire
Créez un système d’inventaire avec les fonctions :
ajouter_a_inventaire(objet)
retirer_de_inventaire(nom_objet)
afficher_inventaire()
Exercice 4 : Interaction complexe
Créez une fonction qui vérifie si le joueur peut ouvrir un coffre :
Le coffre doit être fermé
Le joueur doit avoir la clé dans son inventaire
Si oui, le coffre s’ouvre et donne son contenu
Pour aller plus loin dans votre projet
Maintenant que vous connaissez les dictionnaires, vous pouvez :
Créer un fichier JSON pour stocker vos objets (JSON est basé sur les dictionnaires)
Gérer plusieurs salles avec un dictionnaire de salles
Créer un système de sauvegarde en enregistrant l’état du jeu
Ajouter des dialogues avec des personnages (PNJ)
Implémenter des énigmes complexes avec plusieurs étapes
Un Escape Game est un jeu vidéo où il est question de s’échapper d’une pièce dans laquelle un joueur est enfermé. Pour cela, il fallait découvrir des éléments cachés dans le décor afin de trouver une clé qui permettrait au joueur de s’échapper de la pièce.
Vous allez créer votre jeu à l’aide du module Pygame, en langage python.
Voici un exemple de ce qu’il est possile de réaliser:
Les images qui servent à l’exemple sont à télécharger depuis le dossier source.
Nous partirons du script initial suivant:
# Script mini pour le jeuimportpygame# ============================================# INITIALISATION# ============================================pygame.init()# ==== Création de la fenêtre # ==== et chargement des ressources: ZONE 1LARGEUR=700HAUTEUR=400# --- image fondscreen=pygame.display.set_mode((LARGEUR,HAUTEUR))pygame.display.set_caption("Escape Game")fond=pygame.image.load("salon.png").convert()screen.blit(fond,(0,0))# --- objets interactifs (porte, ...)door1=pygame.image.load("door3.png").convert_alpha()rect1=door1.get_rect()rect1.center=LARGEUR//2+10,(HAUTEUR-100)//2screen.blit(door1,rect1)# --- textefont=pygame.font.Font(None,36)texte="Bienvenue dans la salle mystérieuse"texte_surface=font.render(texte,True,(255,255,255))screen.blit(texte_surface,(0,300))# ==== Variables de contrôle de la boucle et du jeu: ZONE 2running=True# ============================================# BOUCLE PRINCIPALE# ============================================whilerunning:# GESTION DES ÉVÉNEMENTS: ZONE 3foreventinpygame.event.get():ifevent.type==pygame.QUIT:running=Falseelifevent.type==pygame.KEYDOWN:ifpygame.key.name(event.key)=="h":print('HELP')elifevent.type==pygame.MOUSEBUTTONDOWN:ifrect1.collidepoint(event.pos):print("Vous essayez d'ouvrir la porte")# LOGIQUE DU JEU: ZONE 4# (mise à jour des variables du jeu, calculs, etc.)# AFFICHAGE: ZONE 5# Met à jour l'affichagepygame.display.flip()# ============================================# FERMETURE PROPRE# ============================================pygame.quit()
Ajouter d’autres objets
Vous pouvez aussi laisser cours à votre imagination, et dessiner vos propres images.
Par exemple, si vous voulez ajouter une clé, voici l’image en format png (transparence du fond):
Ajouter alors les instructions pour créer une surface et reduire sa taille (ZONE 1)
Image de fond : Un décor de salle (chambre, bureau, etc.)
Objets interactifs : Zones cliquables sur l’image (porte, livres, tableau, bouton de la télévision, etc.)
Zone de texte : Affichage des descriptions et dialogues en bas de l’écran
Touches de commande ou clic sur un objet : Actions possibles (examiner, utiliser, inventaire, obtenir de l’aide, etc.)
Système d’état : Gérer ce qui a été fait ou trouvé: utiliser un dictionnaire pour chacun des objets (voir plus bas). Et modifier, lorsque l’on clique sur l’objet, les variables d’état de l’objet. Par exemple: cle["ramasse"] = True, ou cle["visible"] = False(voir plus bas)
Vous limiterez ainsi l’emploi de trop nombreuses variables:
porte={"nom":"porte","image":door1,"x":650,"y":150,"largeur":100,"hauteur":200,"rect":rect1,"visible":True,"verrouille":True,"description":"Une porte en bois"}cle={"nom":"clé","image":cle,"x":rect3.center[0],"y":rect3.center[1],"largeur":60,"hauteur":27,"rect":rect3,"visible":False,"ramasse":False,"description":"Une clé dorée"}...
Définir un scénario à l’aide de diagrammes
Dans les zones 1 et 2, placer les variables utiles au jeu. Placer les différents textes à afficher.
Dans la zone 3, prevoir les interactions avec les différents objets, ainsi que la modification des variables:
Prévoir diagramme par objet ou par touche appuyée
Dans la zone 5, prévoir l’affichage du texte, ou le nouveau placement des objets/images.
Si vous utilisez un dictionnaire vous pouvez remplacer les variables L, P, M par exemple par lampe["actionner"] = True/False, porte["verouille"] = True/False, et miroir["regarder"] = True/False. Ce qui presente l’avantage d’être plus clair.
Questions à se poser avant de commencer le TP
Quel est le scénario de mon escape game ?
Quels objets ou quelles zones de l’image seront cliquables ?
Les images numériques matricielles sont des tableaux de pixels. On peut concevoir images de synthèse à partir d’instructions en python (ou autre langage). Des librairies comme PIL permettent de manipuler les pixels comme les données d’une table.
Dans cette seance, nous allons:
créer des images de synthèse
modifier des images existantes.
formats de données
Le portable pixmap file format (PPM), le portable graymap file format (PGM) et le portable bitmap file format (PBM) sont des formats de fichier graphique utilisés pour les échanges. Ils correspondent respectivement à des images en noir et blanc (ppm), en niveaux de gris (pgm), et en couleur (pbm).
Les fichiers bruts comportent alors l’indication du format sur leur première ligne avec l’information : P1 pour le format ppm, P2 pour le pgm et enfin P3 pour le pbm.
Couleurs : RVB
Il existe plusieurs modes de codage informatique des couleurs, le plus utilisé pour le maniement des images est l’espace colorimétrique Rouge, Vert, Bleu (RVB ou RVG: Red Green Blue) par synthèse additive.
Une image RVB est composée de la somme des trois rayonnements lumineux Rouge, Vert, Bleu dont les faisceaux sont superposés. A l’intensité maximale ils produisent une lumière blanche 255, 255, 255 en codage décimal, ou FF FF FF en hexadecimal.
profondeur de couleur
norme HD: la profondeur en haute definition est de 1 octet par canal coloré R, V ou B
norme 4K : UHD = 10 bits par canal coloré
Gimp: colorimètre
A vous de jouer: vous allez mesurer l’intensité des couleurs sur l’image suivante
Créer un nouveau dossier pour y mettre tous les fichiers sources et les images.
A l’aide du logiciel Gimp, ouvrir l’image du carré rouge et relever les valeurs RVB du colorimètre.
Synthèse d’images
Rectangle rouge
Vous allez créer une image (rectangle rouge) à partir d’un programme python.
Utiliser un IDE python pour les exercices suivants: Pyzo ou Spyder.
Adopter tout de suite les BONNES PRATIQUES:
pour chaque exercice, vous allez créer un NOUVEAU fichier python.
Donner un nom explicite au fichier, par exemple rouge.py pour le premier exercice
Définir les variables globales largeur et hauteur:
largeur=600hauteur=420
Créer un nouveau fichier texte avec les instructions:
f=open('red_square.ppm','w')############ entête du fichier ##################f.write('P3'+'\n')# P1 était le code pour un pbm format ascii# P3 correspond au ppm format asciif.write(str(largeur)+' '+str(hauteur)+'\n')# valeur max pour l'intensité des couleurs :f.write('255'+'\n')############### fin de l'entête ##################
Definir une fonction pour remplir le fichier avec les valeurs codant la couleur:
######### declaration de la fonction ############defrectangle(couleur,h,l):"""
@param couleur: str
couleur est un triplet d'entiers, code RGB
@example: dessiner un rectangle entierement noir
>>> rectangle('0 0 0',largeur,hauteur)
"""foriinrange(h*l):f.write(couleur+'\n')
Puis appel de la fonction et fermeture du fichier:
rectangle('255 0 0',largeur,hauteur)f.close()
Ajouter la librairie PIL.
Ce qui donne le script complet suivant:
fromPILimportImagelargeur=600hauteur=420#f=open('red_square','w') f=open('red_square.ppm','w')############ entête du fichier ##################f.write('P3'+'\n')# P1 était le code pour un pbm format ascii# P3 correspond au ppm format asciif.write(str(largeur)+' '+str(hauteur)+'\n')# valeur max pour l'intensité des couleurs :f.write('255'+'\n')############### fin de l'entête ########################### declaration de la fonction ############defrectangle(couleur,h,l):"""
@param couleur: str
couleur est un triplet d'entiers, code RGB
@example: dessiner un rectangle entierement noir
>>> rectangle('0 0 0',largeur,hauteur)
"""foriinrange(h*l):f.write(couleur+'\n')######## appel fonction ############################ rectangle('255 0 0',largeur,hauteur)########### fermeture fichier ######################f.close()
Executer le programme avec les commandes de l’IDE python, puis…
Ouvrir le fichier avec un editeur de texte (notepad++) et observer les données.
Ouvrir le fichier avec un logiciel de dessin (GIMP)
Drapeaux de pays
Adopter tout de suite les BONNES PRATIQUES:
pour chaque nouveau défi, vous allez créer un NOUVEAU fichier python.
Donner un nom explicite au fichier, par exemple allemagne.py pour le premier défi, belgique.py pour le 2e…
Adapter maintenant le script du rectangle rouge pour editer en python les drapeau suivants.
Attention à BIEN faire correspondre le nombre de valeurs codantes pour la couleur des pixels. Si le nombre ne correspond par exactement à la dimension $largeur \times hauteur$ définie dans l’en-tête du fichier, vous risquez d’avoir une image sombre (erreur à l’affichage)
drapeau allemand. 3 appels de la fonction rectangle('255 0 0',largeur,hauteur//3)
Attention à bien modifier le nom du fichier généré. Le nommer par exemple drapeau_all.ppm
drapeau belge. Utiliser une boucle bornée pour créer le drapeau ligne par ligne.
motifs périodiques
pour chaque nouveau défi, vous allez créer un NOUVEAU fichier python.
Donner un nom explicite au fichier, par exemple pixart1.py pour le premier défi, pixart2.py pour le 2e…
Dans chaque nouveau fichier, vous allez écrire le script qui va créer les images suivantes, à partir des matrices de valeurs binaires, mat. Dans cette matrice, vous placerez les valeurs en liste (une liste par ligne), et placerez ces lignes dans la matrice mat. Une valeur 0 pourra coder par exemple le bleu, et la valeur 1 le rouge (l’image ne contient que 2 couleurs).
pixart1.ppm
fromPILimportImagelargeur=12hauteur=12f=open('pixart1.ppm','w')############ entête du fichier ##################f.write('P3'+'\n')f.write(str(largeur)+' '+str(hauteur)+'\n')# valeur max pour l'intensité des couleurs :f.write('255'+'\n')############### creation matrice ################mat=[]foriinrange(hauteur):ligne=[]forjinrange(largeur):ligne.append(0)ligne.append(...mat.append(...######### declaration de la fonction ############defcreation_image(M,h,l):"""
@variable couleur: str
couleur est un triplet d'entiers, code RGB
@example: dessiner un pixel entierement noir
>>> couleur = '0 0 0'
"""foriinrange(h):forjinrange(l):ifM[i][j]==1:couleur='255 0 0'else:couleur='0 0 255'f.write(couleur+'\n')######## appel fonction ############################ creation_image(mat,largeur,hauteur)########### fermeture fichier ######################f.close()
pixart2.ppm
Pour chacune de ces images, vous complèterez le script de la fiche de cours.
Lecture puis traitement des pixels de l’image - Partie 2
Lire les pixels de l’image
Dans cette activité, nous allons utiliser la fonction de lecture des couleurs des pixels d’une image. Puis transformer cette image par effet mirroir. Les chatons devront regarder à DROITE après transformation.
Image de chatons à télécharger
La fonction getpixel du module PIL.Image. Cette fonction prend en paramètres les coordonnées du pixel à lire, sous forme d’un tuple (x,y). Exemple:
>>>imageSource.getpixel((x,y))# retourne un tuple constitué des couleurs (R, V, B) du pixel de coordonnée (x,y)
Voici le programme minimal pour ouvrir l’image et déterminer ses dimensions:
Pour lire les couleurs de TOUS les pixels, et appliquer une transformation, on va placer les valeurs dans une matrice, dans un certain ordre:
mat=[[0]*largeurforiinrange(hauteur)]foriinrange(hauteur):forjinrange(largeur):p=imageSource.getpixel((j,i))# j correspond à x # et i <=> ymat[i][j]=p
Puis placer les valeurs de la matrice dans un fichier .ppm, comme vu dans les activités précédentes:
####### ecriture du fichier pour la nouvelle imagef=open('pixart2.ppm','w')f.write('P3'+'\n')f.write(str(largeur)+' '+str(hauteur)+'\n')# valeur max pour l'intensité des couleurs :f.write('255'+'\n')######### declaration de la fonction ############defcreation_image(M):"""
@param couleur: str
couleur est un triplet d'entiers, code RGB
@example: dessiner un rectangle entierement noir
>>> rectangle('0 0 0',largeur,hauteur)
"""h=len(M)l=len(M[0])foriinrange(h):forjinrange(l):couleur=M[i][j]# tuplepixel=str(couleur[0])+' '+str(couleur[1])+' '+str(couleur[2])f.write(pixel+'\n')######## appel fonction ############################ creation_image(mat)########### fermeture fichier ######################f.close()
Comment doit-on placer les pixels dans la matrice pour que les chats regardent de l’autre côté ? Modifier le programme ci-dessus afin d’obtenir cette nouvelle image, avec des petits chats qui regardent à DROITE.
Pix-Art
Avec l’image d’origine suivante:
Marylin Monroe
Apporter les modifications necessaires pour filtrer les couleurs par zone, de manière selective. On pourra obtenir une nouvelle oeuvre inspirée de l’image suivante:
Marylin Monroe type Pop-art
Aide: La condition suivante permet de selectionner les pixels de la partie gauche de l’image, et qui ont une composante Rouge supérieure à 100:
if(j<largeur//2andp[0]>100):# traitement sur p
Ce qui va donner:
mat=[[0]*largeurforiinrange(hauteur)]foriinrange(hauteur):forjinrange(largeur):p=imageSource.getpixel((j,i))if(j<largeur//2andp[0]>100):# traitement sur pmat[i][j]=p
Sur une idée venue de la visite de la collection de Luigi e Peppino Agrati, Naples.
Extrait de l'oeuvre de Andy Warhol (1967). Marilyn.
Ce TP est une variante de celui proposé à l’adresse suivante.
Une conception similaire à l’edition d’un document Word
On utilise des logiciels d’edition, comme Word, Writer, ou Page, pour créer des documents qui seront le plus souvent imprimés (ou mis dans un format pdf).
L’edition va consister à placer du contenu, le structurer, le mettre en forme. Et pour réaliser ceci, la bonne pratique, c’est justement de séparer ces 3 moments, tout en utilisant le même logiciel.
video - youtube
Avec les langages web, HTML et CSS, on edite le document pour le web avec cette même pratique: en séparant les moments (et donc le code) prévus pour ajouter la structure, et ceux prévus pour gérer le style du document.
Des langages interprétés: rôle du navigateur
HTML : HyperTextMarkup Langage; CSS : Cascading StyleSheets; Javascript sont des langages interprétés par le navigateur, côté client. Ces 3 langages, en combinaison, vont permettre de créer des sites internet.
Pour que les pages soient accessibles à tout le monde, sur le web[^2], ces pages doivent être hébergés sur un serveur. Lorsque le navigateur client envoie une requête au serveur, celui-ci lui renvoie les fichiers HTML, CSS et JS. Les instructions sont alors interprétées par le navigateur et permettent l’affichage des pages.
Ces langages sont en constante évolution. Ce sont des langages open sources[^5] et de nombreux contributeurs en proposent des améliorations.
Il existe plusieurs logiciels navigateurs (Mozilla, Chrome, Safari,…). Et pourtant, malgré cette diversité et ces évolutions du langage, ceux-ci vont interpréter ces fichiers et afficher les pages (presque) de la même manière car ils se réferent tous aux mêmes recommandations, celles du w3c[^4].
Une petite différence peut exister pour le rendu d’une même page, mais avec plusieurs navigateurs différents. Cela est du aux propriétés par défaut utilisées par le navigateur pour l’affichage des différents éléments html de la page. Ces propriétés peuvent être déclarées (CSS) afin d’avoir un rendu toujours identique.
Les langages web se partagent les tâches :
Une bonne pratique dans le développement d’un site internet (côté front-end, ce qui est executé sur la machine du client) consiste à utiliser:
HTML pour le contenu , et la structure (avec un contenu correctement balisé, sémantique, accessible)
CSS pour la mise en forme et le design de la page, les propriétés relatives à chaque élément de Style (balise html).
et JavaScript pour gérer les interactions (qui peuvent éventuellement amener à modifier le contenu via les méthodes du DOM[^1]).
C’est un langage de description qui gère le contenu (le texte et les images), en ajoutant des éléments de structure, comme par exemple:
mettre le texte dans un paragraphe
mettre du texte en relief
insérer un hyperlien sur le texte
mettre un titre à la page, au paragraphe
…
Lire la video depuis 20' => 1min40'
Le langage HTML est un langage constitué de balises, comme par exemple :
<title>le titre de ma page</title> qui permet d’afficher le titre de la page dans l’onglet du navigateur.
Les éléments mis dans le programme à l’aide de ces balises vont permettre d’ajouter et structurer le contenu de la page : des titres de différents niveaux, du texte, des images, des médias (sons, videos),mais surtout, des hyperliens :
entre les pages du sites
vers les pages de sites externes
Le web est justement basé sur l’utilisation de ces hyperliens, qui permettent de naviguer de pages en pages, sur internet.
Le HTML et la page Web
le squelette du document
Cette partie du script est le contenu minimum à mettre dans vos pages HTML:
<!DOCTYPE html><html><head><!-- encodage des caractères --><metacharset="UTF-8"><!-- Titre --><title>Titre de la page web</title><!-- Lien vers la feuille de style --><linkrel="stylesheet"type="text/css"href="style.css"></head><body><!-- corps de la page --></body></html>
Le doctype indique au navigateur la version HTML utilisée par la page (ici HTML5).
L’élément racine <html> : C’est lui qui va recueillir les deux principaux éléments de la hiérarchie : <head> et <body>.
À ce niveau, le code HTML est alors divisé en deux parties.
On peut lui associer l’attribut langue, précisant la langue utilisée dans le document :
<html lang="fr">
L’en-tête (élément <head>) donne l’encodage des caractères (ici UTF-8).
Préciser l’encodage des caractères est primordial pour exploiter la bonne page de code et ne pas se retrouver avec les caractères spéciaux ou accentués. Le choix de l’UTF-8 est désormais préconisé par le W3C pour tous les protocoles échangeant du texte sur internet (dont HTML).
On peut aussi y ajouter des éléments <link> et <script> :
link : permet de mettre en relation la page avec d’autres documents externes:
<link rel="stylesheet" type="text/css" href="style.css">
<script> permet d’ajouter des scripts (JavaScript) qui vont s’éxécuter côté client dans le navigateur dès leur chargement.
Si vous avez un script qui est très gros mais indépendant, il est préférable de le placer tout à la fin, afin de ne pas retarder le navigateur dans sa construction de l’arbre du DOM et de l’affichage de la page.
Les balises principale
Les balises sont les instructions en langage HTML des éléments structurants de la page web.
Les balises se distinguent entre celles qui n’ont pas d’attribut obligatoire, et celles qui en ont. Un attribut va ajouter des fonctionnalités à l’élément HTML, et modifier son allure ou son fonctionnement.
Balises sans attribut
Les principales balises structurantes sont:
h1, h2, h3, … h6
div
p
span
strong
…
Elles s’utilisent de la manière suivante:
<h1>Texte</h1><p>Texte</p>
Il existe aussi des balises qui doivent être combinées, comme celles de listes:
ul (parent) => li (enfants) pour une liste à puces
ol (parent) => li (enfants) pour une liste ordonnée (numérotée)
Les attributs seront obligatoires pour certaines balises selon leur fonction. Certains attributs sont facultatifs et vont juste enrichir leur comportement.
L’imbrication des balises traduit le lien (la filiation) entre les éléments.
On représente la structure d’un document html à l’aide d’un arbre.
On parle d’arbre DOM (Document Object Model) du document.
Exemple d'arbre du DOM
Pour cet exemple:
Le nœud article est le père des noeuds h1, p, img et p.
Les nœuds h1, p, img et p sont les fils du nœud article.
Quand faut-il recourir à des balises parentes?
Supposons que l’on ait besoin de structurer la page comme sur l’image suivante:
page avec sectionnements
Les éléments containers s’ils sont de type paragraphes, sections, header, nav, article, … vont se placer naturellement l’un sous l’autre. Il n’y a pas besoin d’imbriquer les balises.
Par contre, s’il faut disposer côte à côte 2 éléments containers, pour faire 2 colonnes, il faudra les disposer à l’interieur d’un autre élément parent. Puis modifier leur disposition naturelle (paramètre display).
Pour cet exemple, au niveau de l’élément au fond blanc, il faudra:
un container parent, par exemple un élément div
(colonne gauche): un container fils de div qui contiendra lui-même les éléments fils ‘section, article, article`
(colonne droite): un élément fils de div qui sera l’élément aside
Pour vérifier que votre page Web est conforme aux spécifications HTML5, rendez-vous sur le site du W3C (World Wide Web Consortium) : http://validator.w3.org
Pour une page Web locale (pas encore publiée sur le Web) :
Validate by File Upload → Check
S’il y a des erreurs, elles vous seront indiquées, avec des explications (en anglais, of course).
Conseil : vérifier et corriger systématiquement vos pages Web avec cet outil.C’est contraignant au début, mais cela vous fera prendre rapidement de bonnes habitudes.
L’essentiel à retenir
Le Web
Le web fonctionne avec : le protocole HTTP (HyperText Transfert Protocol), les URL (Uniform Resource Locator) et le langage de description HTML (HyperText Markup Language).
Le W3C
Le World Wide Web Consortium, abrégé par le sigle W3C, est un organisme de standardisation à but non lucratif, fondé en octobre 1994 chargé de promouvoir la compatibilité des technologies du World Wide Web telles que HTML, CSS, JS… Le W3C permet la normalisation de la présentation de l’information.
Le HTML
HTML (HyperText Markup Langage) permet de structurer le contenu de la page web. C’est un langage interprété par le navigateur (client).
C’est un langage constitué de balises. La plupart du temps, le contenu se met entre les balises ouvrantes / fermantes. Mais il existe des balises orphelines qui n’ont pas de fermeture (img, br).
Le squelette du document est constitué du doctype (première ligne), puis des éléments html, head, et body.
La manière avec laquelle les balises sont imbriquées correspond à une filiation entre les éléments (parent-fille). Ainsi, html est la balise parente de toutes les autres. html est aussi le parent direct de head et body.
Le contenu de la page sera mis entre les balises de body.
Le CSS
Le langage CSS (Cascading Style Sheets) est le langage de mise en forme d’une page web. C’est un langage interprété par le navigateur. Le lien vers la feuille de style est souvent insérée dans l’en-tête de la page web:
<link href="style.css" rel="stylesheets">
Le Javascript
Langage utilisé pour les scripts cöté client. Permet de gérer l’interactivité d’une page web, son aspect dynamique. L’aspect étant reservé aux langages HTML et CSS.
Le lien vers le fichier contenant le script javascript est souvent insérée dans la page web:
<script src="script.js">
Tâches synchrones et asynchrones
Deux opérations sont synchrones lorsque la seconde attend que la première ait fini son travail pour démarrer. Par exemple, le protocole HTTP (lors du chargement et rechargement d’une page web), mais aussi l’interprétation des langages HTML et CSS par le navigateur.
Des opérations sont asynchrones en informatique lorsqu’elles sont indépendantes. Souvent, le navigateur interprète les scripts javascript de manière asynchrone, ce qui ne créé pas de blocage lors de la construction de la page.
Toujours côté client, la technologie AJAX permet le transfert de données en arrière plan, sans avoir à recharger la page web.
Scripts côté serveur
Les scripts côté serveur nécessitent une communication avec le serveur de manière synchrone ou asynchrone. Ils serviront par exemple à collecter des données, à générer le code HTML de la page, à communiquer avec une base de données. Les langages les plus utilisées sont PHP, Python, Javascript …
Les sigles « CSS » sont l’abréviation de « Cascading StyleSheets » ou « feuilles de styles en cascade » en français.
Le CSS vient résoudre un problème bien différent du HTML : en effet, le HTML sert à définir les différents éléments d’une page, à leur donner du sens. Le CSS, lui, va servir à mettre en forme les différents contenus définis par le HTML en leur appliquant des styles.
Si votre navigateur affiche par défaut les contenus textuels que vous avez déclaré comme des titres en HTML en grand et en gras et à l’inverse les paragraphes en plus petit c’est justement parce que chaque navigateur possède sa propre feuille de styles. En fournissant nos styles CSS pour les différents contenus de notre page, nous allons donc pouvoir définir l’apparence de ceux-ci puisque les styles que nous allons fournir vont être considérés comme prioritaires par rapport à ceux du navigateur. C’est le principe du style en cascade (CSS)
Une déclaration en CSS
Une règle typique est composée de trois parties :
un sélecteur,
une propriété,
une valeur
selecteur { propriete: valeur; }
La valeur de la propriété se met après le séparateur :.
Ces règles deviennent des déclarations lorsque celles-ci comprennent plusieurs couples propriété-valeur :Les règles sont alors séparées par un point-virgule ;, dans la même accolade:
selecteur{propriete1:valeur;propriete2:valeur;}
Le selecteur fait référence à un ou plusieurs éléments du document.
indexer les parties du document
Classes et identifiants
L’un des attributs des éléments HTML peut servir à indexer cet élément :
de manière unique : l’attribut id="valeur" : une seule valeur d’attribut id peut être utilisée dans tout le document HTML. L’attribut id sert, comme son nom l’indique, à identifier un élément HTML en particulier
dans une page pour ensuite pouvoir le cibler précisément (pour lui appliquer des styles CSS, ou bien créer un lien vers cet élément).
avec un attribut de classe : class="valeur" : ici, plusieurs éléments peuvent avoir la même classe. On pourra alors séléctionner (en css et en javascript) tous les éléments possédant cette classe, avec une seule instruction.
Remarque: Plusieurs classes peuvent être associées à un élément HTML en les séparant par un espace : <h1 class="titre lexique">
Selecteurs
Pour pouvoir appliquer un style à un contenu, il va déjà falloir le cibler, c’est-à-dire trouver un moyen d’indiquer qu’on souhaite appliquer tel style à un contenu en particulier.
Pour cela, nous allons utiliser des sélecteurs.
selecteur
effet
h1
Le nom d’une balise. Toutes les balises de ce nom contenues dans le document seront concernées.
h1,h2,h3
Plusieurs sélecteurs séparés par des virgules.Toutes les balises énumérées sont concernées.
#logo
Le caractère # indique un identifiant. La balise avec cet ID est concernée.Exemple img id=“logo” src="…"/.
.bidule
Le point introduit une classe. Toutes les balises comportant un attribut class de ce nom sont concernées.Exemple : p class=“bidule”
tab img
Plusieurs sélecteurs séparés par un espace : inclusion. Les balises img incluses dans un tableau sont concernées. Il peut exister des niveaux intermédiaires : ici il y aura probablement au moins des balises tr et td.
Règles principales
Principe
Le CSS permet d’ajouter des propriétés aux éléments (html) de la page. Par exemple, pour realiser la ligne suivante, avec une partie du texte en gras, et une partie en caractères normaux, non gras:
Acteur: Daniel Crog
On peut, soit utiliser une balise inline <strong> placée avant le texte (propriété font-weight: bold), soit une balise inline générique, et placer une instruction CSS. Ces 2 choix vont donner le même résultat:
<!-- choix n°1--><strong>Acteur:</strong> Daniel Crog
<!-- choix n°2--><spanstyle="font-weight: bold">Acteur:</span> Daniel Crog
Les balises s’affichant en “block” (bloc) : elles prennent toute la largeur disponible et s’affichent avec un saut de ligne avant et après. On peut les dimensionner avec les propriétés width et height. Elles n’accèptent pas vertical-align
Les balises s’affichant en “inline” (dans la ligne) : elles prennent uniquement la largeur utile pour leur contenu, sans ajouter de saut de ligne. Elles acceptent vertical-align, mais pas width et height.
L’héritage des CSS est fondé sur le modèle Parent-Enfant(s) : chaque élément Enfant reçoit en héritage tous les styles de son élément Parent. Par exemple, la balise <html> est parent de <body>, et <table> est parent de <tr> qui lui-même est parent de <td>. Cet héritage est très pratique et permet d’éviter beaucoup de répétitions inutiles.
Précision : l’élément enfant héritera de toutes les propriétés de l’élément parent uniquement si ces propriétés s’héritent, car l’héritage ne fonctionne pas non plus sur toutes les propriétés css (margin, padding et autres propriétés de bloc).
Pour appliquer une propriété de style “par défaut” à un document, un auteur peut l’appliquer à la racine de l’arbre du document.
Par exemple ici, tous les descendants de l’élément BODY auront la valeur de couleur ‘black’, la propriété ‘color’ étant héritée :
BODY { color: black; }
Les valeurs de pourcentage spécifiées ne sont pas héritées, celles calculées le sont.
Par exemple, cette feuille de style :
BODY { font-size: 10pt }
H1 { font-size: 120% }
et cet extrait d’un document :
<BODY>
<H1>Un <EM>grand</EM> titre</H1>
</BODY>
Ici, la propriété ‘font-size’ de l’élément H1 aura une valeur calculée de ‘12pt’ (120% de la valeur de son parent). Et, comme la valeur de la propriété ‘font-size’ est héritée, la valeur calculée pour l’élément EM sera aussi ‘12pt’.
Selection, compléments
selecteur
effet
td > img
Plusieurs sélecteurs séparés par un caractère supérieur : inclusion directe.Les balises img directement incluses dans une cellule de tableau sont concernées. Il ne doit pas exister de niveaux intermédiaires.
td + img
Plusieurs sélecteurs séparés par un signe + : vient après.Désigne les balises img venant après une balise p.
p ~ img
Plusieurs sélecteurs séparés par un signe ~ : une balise qui suit une autre (directement ou pas)
:hover
Le caractère : (deux points) introduit une pseudo-classe. La pseudo-classe désigne un élément lorsqu’il se trouve dans une certaine situation : ici lorsqu’il est survolé par la souris.Voir la liste complète des pseudo-class.
img[width]
Désigne les balises img comportant un attribut width quelle que soit la valeur de ce dernier. On teste donc seulement la présence de l’attribut.
p[lang = “fr” ]
Ici on limite la portée aux balises p qui comportent l’attribut lang avec la valeur “fr”.p lang=“fr”
Exemple: mise en couleur de fond gris pour une cellule sur 2 du tableau
Ce cours présente les concepts de base de JavaScript en les comparant avec Python, que vous connaissez déjà. JavaScript est le langage de programmation du web : il permet de rendre les pages interactives.
Principales différences avec Python :
JavaScript s’exécute dans le navigateur (côté client)
La syntaxe utilise des accolades {} au lieu de l’indentation
Il existe plusieurs façons de déclarer des variables
JavaScript manipule directement les éléments HTML (le DOM)
Présentation de la console javascript
Javascript est une implémentation dans le navigateur du langage Ecmascript.
Javascript est un langage interprété … par le navigateur, donc côté client.
Pour le vérifier, on peut utiliser la console javascript du navigateur pour tester quelques instructions, et interagir avec la page web en cours.
Sur Chrome, cette console se trouve en ouvrant les outils de développement :
la console javascript dans le navigateur Chrome
Choisir alors l’onglet : Console et commencer à taper les instructions, une à une, après l’invite >, comme sur l’image suivante :
entrée / sortie
Pour afficher le résultat d’une opération dans la console (équivalent au print en python), on utilise l’instruction console.log(operation).
L’option filter de la console devra être sur Default
Les Variables : let, const et var
En Python (rappel)
En Python, on déclare une variable simplement :
# Une variable simpleage=15nom="Alice"# On peut la modifierage=16
En JavaScript : trois mots-clés
JavaScript propose trois façons de déclarer une variable :
letage=15;// Variable qui PEUT changer
constnom="Alice";// Constante qui NE PEUT PAS changer
varancien=10;// Ancienne syntaxe (à éviter)
Le typage est dynamique, comme en python: il n’est pas besoin de préciser le type.
Règle d’utilisation
Mot-clé
Usage
Peut changer ?
Recommandation
const
Valeur fixe
[X] Non
À utiliser par défaut
let
Valeur variable
[V] Oui
Quand la valeur change
var
Ancienne syntaxe
[V] Oui
À éviter (obsolète)
Exemples concrets
// Utiliser const par défaut
constpi=3.14159;// Ne changera jamais
constnom="Alice";// Ne changera jamais
constbouton=document.getElementById('monBouton');// Ne changera jamais
// Utiliser let quand ça change
letcompteur=0;// Va augmenter
lettemperature=20;// Peut varier
letscore=0;// Va évoluer
// Erreur : on ne peut pas modifier une const
constage=15;age=16;// ERREUR : Assignment to constant variable
// Correct : on peut modifier un let
letage=15;age=16;// OK
Remarque : A moins que vous soyez sûr que la valeur puisse être modifiée, déclarez vos variables avec const, puis changez en let seulement si le compilateur vous indique une erreur.
Quelques différences Python ↔ JavaScript
Python
JavaScript
age = 15
let age = 15;
PI = 3.14 (convention)
const PI = 3.14; (imposé)
Pas de point-virgule
Point-virgule ; recommandé
print(age)
console.log(age)
Le DOM : Document Object Model
Qu’est-ce que le DOM ?
Le DOM est la représentation en mémoire de votre page HTML. JavaScript peut :
Lire les éléments HTML
Les modifier
Créer de nouveaux éléments
Réagir aux actions de l’utilisateur
Analogie avec Python :
# En Python, vous manipulez des fichiersfichier=open('data.txt','r')contenu=fichier.read()fichier.close()# En JavaScript, vous manipulez des éléments HTMLelement=document.getElementById('monId')contenu=element.textContent
Récupérer un élément : getElementById()
HTML de départ
Placer un attribut id aux balises que l’on veut indexer.
<h1id="titre">Bienvenue</h1><pid="description">Ceci est un paragraphe</p><buttonid="monBouton">Cliquez-moi</button>
JavaScript
<script>// Récupérer les éléments
consttitre=document.getElementById('titre');constdescription=document.getElementById('description');constbouton=document.getElementById('monBouton');console.log(titre);// Affiche: <h1 id="titre">Bienvenue</h1>
</script>
A faire vous-même (1): Placer les 2 parties du script ci-dessus dans une même page (page.html). Ouvrir avec un navigateur.
Remarque importante : L’ID doit être exactement le même (sensible à la casse)
// Correct
constelement=document.getElementById('monBouton');console.log(element);// Affiche <button id="monBouton">Cliquez-moi</button>
// Erreur : mauvaise casse, ou ID inexistant
constelement=document.getElementById('MonBouton');console.log(element);// Affiche: null
Attributs vs Propriétés
Comprendre la différence
Un élément HTML possède :
Des attributs (définis dans le HTML)
Des propriétés (accessibles en JavaScript)
Exemple HTML
<inputtype="text"id="champNom"value="Alice">
Les attributs (dans le HTML)
type="text"
id="champNom"
value="Alice"
Les propriétés (en JavaScript)
constchamp=document.getElementById('champNom');// Propriétés disponibles :
champ.type// "text"
champ.id// "champNom"
champ.value// "Alice" (peut être modifié par l'utilisateur)
champ.textContent// ""
champ.style// Objet avec toutes les propriétés CSS
La notation pointée
En JavaScript, on accède aux propriétés avec un point (comme en Python) :
# Python: notation pointée pour objet.attribut ou objet.methode()foreventinpygame.event.get():ifevent.type==pygame.QUIT:running=False
// JavaScript : notation pointée pour les éléments HTML
constelement=document.getElementById('titre');// Lire une propriété
console.log(element.textContent);// "Bienvenue"
console.log(element.id);// "titre"
// Modifier une propriété
element.textContent="Nouveau titre";element.style.color="red";
Propriétés courantes
textContent : Le texte à l’intérieur
<pid="message">Bonjour tout le monde</p>
A faire vous-même (2): Placer dans votre page.html le paragraphe Bonjour tout le monde. Ouvrir la console Web et placer l’une après l’autre chacune des instructions javascript ci-dessous.
constmessage=document.getElementById('message');// Lire le texte
console.log(message.textContent);// "Bonjour tout le monde"
// Modifier le texte
message.textContent="Nouveau message";// Le HTML devient : <p id="message">Nouveau message</p>
// JavaScript
functionafficherMessage(){console.log("Message affiché");}// Ou avec fonction fléchée
constafficherMessage=()=>{console.log("Message affiché");};
// Récupération des éléments
constbouton=document.getElementById('bouton');constaffichage=document.getElementById('affichage');// Variable compteur
letcompteur=0;// Fonction d'incrémentation
functionincrementer(){compteur++;affichage.textContent=compteur;}// Associer la fonction au clic
bouton.addEventListener('click',incrementer);
let compteur = 0 : Variable qui va changer (on utilise let)
function incrementer() : Déclare la fonction
compteur++ : Ajoute 1 au compteur (équivalent à compteur += 1)
affichage.textContent = compteur : Met à jour le texte affiché
addEventListener('click', incrementer) : “Quand on clique, exécute la fonction”
Exercices d’application
Exercice 1 : Variables
Complétez le code suivant :
// 1. Déclarez une constante PI valant 3.14159
// 2. Déclarez une variable score initialisée à 0
// 3. Augmentez le score de 10
// 4. Affichez le score dans la console
// BONNE PRATIQUE : const pour les références
constbouton=document.getElementById('btn');constaffichage=document.getElementById('resultat');// Ces éléments ne changeront jamais, même si leur contenu change
bouton.textContent="Nouveau texte";// OK !
affichage.textContent="Score: 10";// OK !
// On ne peut pas réassigner à un autre élément
bouton=document.getElementById('autre');// ERREUR
Javascript, c’est aussi le langage de script des pages web : on peut aussi :
Mettre son code javascript entre les balises <script> et </script> d’une page HTML. Cette page est construite au fur et à mesure du parcours par l’interpreteur. La partie javascript sera interprétée APRES l’affichage de la page par le navigateur si cet élement script est mis à la fin du document HTML.
Mettre son code dans un fichier externe : Il faudra d’abord lier le fichier javascript à celui HTML :
<script src="monfichierJavascript.js"></script>
Principe : le rôle du navigateur et son moteur javascript
l'interpreteur javascript
Browser : navigateur. C’est est un logiciel conçu pour consulter et afficher le World Wide Web. Techniquement, c’est au minimum un client http ou https (qui sont des protocoles de communication, définis lors du dernier cours)
Web console : Permet de coder, d’interpréter et d’exécuter du code Javascript directement sur le Browser
Js Engine : Est intégré dans les Browser. Chaque Browser a son propre interpréteur Javascript qui interprète le code et exécute les scripts associés aux pages Web
En EcmaScript, on passe la majeure partie de son temps à interagir avec des API fournis par l’environnement d’exécution. En ActionScript c’est Flash (objet flash), en JavaScript dans le navigateur c’est le Document Object Model (objet document).
Structurer son code
La javascript utilise certains symboles pour structurer :
à chaque ligne on met un point-virgule pour séparer les instructions
les accolades { et } séparent les blocs de code
Commenter son code : // en debut de ligne ou bien /* texte entre les 2 separateurs */
//Commentaire sur une ligne
/*Commentaire sur
Plusieurs ligne */
Les indentations, comme en python ne sont pas obligatoires pour structurer le code, mais fortement conseillées pour permettre une meilleure lisibilité.
Les 3 Data types de bases
Les 3 types simples
Pour déclarer une variable, on utilise le mot clé : let (ou bien var, mais qui n’est plus préconisé par le w3c)
Par exemple : let a = 10 ; let b = “toto“ ;
Le typage des variables se fait alors de manière dynamique, comme en python.
Number : Représente à la fois les entiers et les nombres flottants.
Pour connaître le type d’une variable, on utilise la fonction typeof(variable)
conversions de types
a. Convertir en nombre entier : parseInt(‘valeur’)
b. Convertir en nombre flottant : parseFloat()
c. Tester si la valeur est NaN (not a number) : isNaN()
d. Convertir en chaine de caractère : string(variable) avec un ‘S’ majuscule.
Les tableaux: type Array
Les tableaux, array, sont des collections d’objets, mis et ordonnés dans une variable unique. On accède à chaque élément du tableau avec son rang. Cette structure de données est assez proche de la liste que l’on a vu en python.
Déclarer un tableau vide : 2 manières :
let tab = new Array() ;
let tab = [] ;
initialiser un tableau :
Pour déclarer et affecter directement des éléments, on fait :
Un objet est un ensemble de propriétés et une propriété est une association entre un nom (aussi appelé clé) et une valeur. C’est l’équivalent des dictionnaires python.
On peut définir une propriété en lui affectant une valeur. Ainsi, si on crée un objet maVoiture et qu’on lui donne les propriétés fabricant, modèle, et année :
On retrouve les opérateurs déjà vus en langage python :
Opérateurs de base : +, -, *, / ainsi que l’opérateur % modulo (reste de la division)
**est l’opérateur exposant : 2**8 correspond à 2^8 (à la puissance 8)
Le symbole d’affectation est le =. Par exemple :
let a = 10 ; // instruction qui declare et affecte 10 à la variable a
Question 1 : Alice a 1 frère et 3 sœurs pour 8 bonbons. Elle voudrait partager les bonbons équitablement. Utiliser des variables pour trouver une solution à son problème.
Question 2 : Coder un programme qui permet de savoir l’âge d’Alice (28 ans) en secondes. Réaliser les calculs avec des variables aux noms bien explicites pour les heures, jours, années. Si vous pouvez, utilisez des noms en langue anglaise pour les variables.
Les opérateurs logiques
est égal ==, est supérieur ou égal >=, inferieur ou égal <=, et &&, ou ||, non !. On peut aussi utiliser and, or, not pour ces 3 derniers opérateurs.
Fonctions
function .. return
Une fonction se définit avec le mot clé function selon la structure :
function nom_de_la_fonction(parametre1, parametre2, …) {
bloc de code
return valeur_à_retourner ;
}
Par exemple, pour programmer une fonction nommée f qui retourne le résultat du calcul :
while (condition à realiser pour boucler) {
bloc de code
}
Par exemple, pour afficher les entiers de 0 à 2 :
let i = 0 ;
while (i<3) {
console.log(i) ;
i ++ ;
}
La grande différence avec une boucle bornée, c’est que l’instruction qui modifie la variable i est DANS le bloc de code. Si celle-ci est mal écrite, la boucle risque d’être exécutée indéfiniment (à éviter bien sûr).
Liens
parcours for pour les éléments d’un objet: MDN mozilla
Concepts avancés et Jeu d’arcade en javascript (hors programme): Page 3
Flask est une bibliothèque python fournissant les outils pour faire fonctionner un serveur web.
Fonctionnement de Flask
L’architecture Modèle-Vue-Contrôleur est composée de trois entités distinctes, chacune ayant son propre rôle:
Le contrôleur: gère le fonctionnement du site Web. Le programme est écrit en python.
Les vues: cette partie se concentre sur l’affichage, et a pour rôle d’assembler le code HTML issu du template. Dans une vue, on peut mettre en oeuvre des algorithmes écrits en python. La vue va partager des variables avec les templates.
Les templates: c’est le modèle de la page HTML qui sera utilisée par la vue pour générer la page HTML envoyée au client. Cette page peut être personnalisée selon les variables partagées avec la vue. C’est grâce à certaines parties écrites en langage JINJA2, dans le corps du script du template que la substitution des éléments HTML sera réalisée. Un peu comme un texte à trous.
créez un fichier Python “main.py” (ce fichier devra être sauvegardé dans le répertoire “serveur_form” précédemment créé).
Saisissez le code suivant dans le fichier “main.py”
Ce fichier main.py contient les vues (les pages), et lance le contrôleur lorsqu’il est executé.
Executer le programme ci-dessus
ouvrez votre navigateur web et tapez dans la barre d’adresse “localhost:5000”
Vous devriez voir la phrase “Tout fonctionne parfaitement” s’afficher dans votre navigateur.
Explications
notre serveur et notre client se trouvent sur la même machine, avec le “localhost”, on indique au navigateur que le serveur web se trouve sur le même ordinateur que lui (on parle de machine locale).
La barre d’adresse doit être renseignée avec l’adresse du serveur web: http://127.0.0.1:5000 ou bien http://localhost:5000
En exécutant le programme Python ci-dessus, le framework Flask a lancé un serveur web. Ce serveur web attend des requêtes HTTP sur le port 5000. En ouvrant un navigateur web et en tapant “localhost:5000”, nous faisons une requête HTTP.
Cette requête demande au serveur de lui retourner la ressource située à la racine du site Web.
Le serveur web fourni avec Flask répond à cette requête HTTP en envoyant une page web (une vue) contenant uniquement <p>Tout fonctionne parfaitement</p>. C’est ce qui est retourné par la fonction index et le groupe de lignes:
Dans la console de l’IDE python, nous voyons ainsi les requêtes et les éventuelles erreurs. C’est un bon moyen de visualiser les requêtes vers le serveur.
Par exemple lorsque vous avez ouvert le navigateur à l’adresse 127.0.0.1:5000/ vous avez eu une ligne qui est apparu dans la console :
Celui-ci contiendra les éléments input de type text et nommés nom et prenom, ainsi qu’un bouton pour envoyer les données du formulaire.
Le formulaire utilisera la méthode POST pour envoyer les données. Celles-ci vont parvenir à la page result.
La page result.html
Saisir le script HTML (notepad ++) suivant dans le fichier result.html du dossier templates:
<!doctype html><htmllang="fr"><head><metacharset="utf-8"><title>Résultat</title></head><body><p>Bonjour {{prenom}} {{nom}}, j'espère que vous allez bien.</p></body></html>
Cette requête POST sera envoyée à l’URL http://localhost:5000/result (voir l’attribut “action”). Les données saisies dans le formulaire seront envoyées au serveur par l’intermédiaire de cette requête.
En réponse à la requête POST, le serveur renvoie une page HTML créée à partir du template resultat.html et des paramètres nom et prenom.
Vous remarquerez que cette page contient des éléments d’un autre langage: {{prenom}} {{nom}}. Il s’agit d’instructions en Jinja2, un langage serveur comme PHP.
Ce langage est executé côté serveur et il génère des bouts de script HTML AVANT que la page ne soit retournée au client.
Ici, ce seront les contenus de variables qui remplacent {{prenom}} {{nom}} dans le script HTML.
Observez comment la fonction result va ouvrir la page result.html tout en passant les variables nom et prenom, par la méthode POST.
Observez également la ligne précédent la definition de la fonction result:
celle-ci contient un décorateur, @app.route('/result'... sur l’objet app de la librairie flask qui précise le chemin vers le fichier à ouvrir: /result.html
moniteur reseau
méthode POST
Ouvrir le moniteur reseau. Utiliser la page de formulaire, envoyer les donées. Dans le moniteur, cliquer sur l’onglet header.
Observer l’URL de la requête client. Celle-ci comporte-t-elle des paramètres query?
Observer le champ formulaire: contient-il l’information des données transmises?
Exemple de moniteur reseau (Chrome)
méthode GET
On peut modifier la méthode HTTP utilisée (POST) par la méthode GET. Cela modifie le traitement des données (python)
Ouvrir le moniteur reseau et recommencer l’opération (transmettre les données par le formulaire):
Observer l’URL de la requête client. Celle-ci comporte-t-elle des paramètres query?
Observer le champ Query String parameters: contient-il l’information des données transmises?
Prolongements possibles
Ajouter des pages statiques
Vous pouvez ajouter des pages dans le dossier templates.
Pour des pages statiques, le script contiendra les instructions en HTML que vous connaissez. Les pages peuvent être liées par des liens. Exprimez les liens à partir de la racine / du site.
Exemple: <a href="/">Lien</a> dirigera vers la page d’accueil du site.
Il faudra ajouter une vue vers chacune des nouvelles pages depuis le fichier main.py. Par exemple, supposons que vous avez créé une page test.html dans le dossier templates. Ajouter alors les lignes suivantes dans le fichier main.py:
La page est alors accessible depuis l’adresse http://localhost:5000/test, ou bien http://127.0.0.1:5000/test
Traitement des valeurs du formulaire
C’est au niveau des lignes suivantes que l’on récupère les informations du formulaire:
n=result['nom']p=result['prenom']
Il est possible des diriger vers un page différente selon la valeur des informations. On peut imaginer que l’administrateur du site va ouvrir une page différente:
Pour la séance de TP, il est recommandé d’ajouter les instructions CSS directement dans le fichier HTML, avec les balises <script> (plus facile). Mais dans une démarche de projet, on peut mettre le code css dans un fichier externe.
Créer un nouveau dossier, appelé static à la racine du dossier du projet. L’arborescence ressemble alors à:
On peut egalement demander un entier aleatoire entre 0 et 100 avec la fonction int:
>int(100*random())62
Ecrire un programme qui affiche de manière aléatoire la chaine de phonèmes “Ke”, “KeKe”, “KeKeKe” ou “KeKeKeKe”, …, avec “Ke” répété un nombre aléatoire de fois, entre 1 et 10.
On veut maintenant que le programme affiche un texte aléatoire pouvant aussi comporter des séquences de “Ki”, “Di”, “Bi” comme par exemple: “KeKiDiBiBi”. La séquence devra avoir une longueur inférieure ou egale à 10 phonèmes et pourra comporter des repetitions.
Programmer une fonction texte_aleatoire qui prend en paramètres les 4 phonèmes son1, ‘son2’, son3, son4. La fonction retourne un texte aleatoire de 10 sons maximum. Lors de l’appel de cette fonction avec texte_aleatoire("Ke","Ki","Di","Bi"), cette fonction pourrait retourner par exemple : “KeKiDiBiBi”
Calendrier
1. Ecrire un programme qui indique si une année a est bissextile. Une année est bissextile si elle est divisible par 4.
2. Compléter le programme pour calculer le nombre de jours du mois m. m étant un entier compris entre 1 et 12. De janvier à juillet, les mois impairs ont 31 jours, les autres 30. Sauf le mois de fevrier a 29 ou 28 selon que l’année est bissextile ou non. Pour les autres mois, du mois d’aout à décembre c’est l’inverse (31 jours pour les m pairs).
3. Ecrire une fonction jour_semaine qui détermine le jour de la semaine à une date donnée. On représente les jours par les nombres 0 = lundi, 1 = mardi, … 6 = dimanche.
defjour_semaine(jour,mois,annee,jour0):"""retourne le jour de la semaine à une
date donnée. jour0 est le code du premier
jour de l'année"""
4. Vérifier que le 14 juillet 2022 tombe un jeudi.
Fonction sin
1. Ecrire un programme qui utilise une boucle pour afficher les valeurs de la fonction sin pour x entre 0 et π
On découpera l’intervale [0; π] de façon à afficher 15 valeurs de sin(x).
Pour utiliser la fonction sin, il faudra l’importer avec la librairie math:
Exemple d’import de la fonction sin et de la constante PI en console:
>frommathimportsin,pi>sin(pi/2)1.0
Exemple de valeurs obtenue pour sin(x), où x est dans [0; π]
2. Pour afficher le graphe de la fonction sin, on peut remplacer chaque valeur calculée précédement par une barre horizontale de longueur proportionnelle à sa valeur.
On pourra par exemple multiplier le résultat de sin(x) par 30, et utiliser la fonction int pour transformer le nombre en entier, afin d’afficher un nombre de barres entre 0 et 30: int(30 * sin(x)) Utiliser le programme pour afficher un graphique qui aura l’allure suivante:
3.(difficile) Modifier le programme pour afficher maintenant la courbe entière de sin sur une période entière, c’est à dire pour x compris dans l’intervale [0, 2π]
1. Ecrire un programme qui, étant donné un nombre entre 2 et 12, affiche toutes les combinaisons possibles permettant d’obtenir ce nombre avec 2 dés.
Par exemple, pour obtenir 7, il pourrait afficher:
'1 ET 6 , 2 ET 5 , 3 ET 4 , 4 ET 3 , 5 ET 2 , 6 ET 1 , '
Aide: Pour faire une boucle bornée, avec un variant qui va de 1 à 6, on peut faire:
foriinrange(1,7):...
2. Etendre ce programme pour afficher, pour chaque nombre entre 2 et 12, toutes les combinaisons possibles permettant d’obtenir ce nombre avec les 2 dés.
Par exemple:
Pour obtenir 2, on peut faire 1 ET 1 ,
Pour obtenir 3, on peut faire 1 ET 2 , 2 ET 1 ,
Pour obtenir 4, on peut faire 1 ET 3 , 2 ET 2 , 3 ET 1 ,
Pour obtenir 5, on peut faire 1 ET 4 , 2 ET 3 , 3 ET 2 , 4 ET 1 ,
Pour obtenir 6, on peut faire 1 ET 5 , 2 ET 4 , 3 ET 3 , 4 ET 2 , 5 ET 1 ,
Pour obtenir 7, on peut faire 1 ET 6 , 2 ET 5 , 3 ET 4 , 4 ET 3 , 5 ET 2 , 6 ET 1 ,
Pour obtenir 8, on peut faire 2 ET 6 , 3 ET 5 , 4 ET 4 , 5 ET 3 , 6 ET 2 ,
Pour obtenir 9, on peut faire 3 ET 6 , 4 ET 5 , 5 ET 4 , 6 ET 3 ,
Pour obtenir 10, on peut faire 4 ET 6 , 5 ET 5 , 6 ET 4 ,
Pour obtenir 11, on peut faire 5 ET 6 , 6 ET 5 ,
Pour obtenir 12, on peut faire 6 ET 6 ,
3. Modifier le programme pour faire la même chose avec 3 dés.
exos tableaux listes python
Partie 1 : Tableaux 1D - Accès par indice
Exercice 1.1 : Gestion d’un inventaire de jeu vidéo
Vous développez un jeu de rôle où le personnage possède un inventaire de 10 emplacements. Chaque emplacement contient un objet représenté par une chaîne de caractères.
# Pour afficher l'objet à l'indice 2print(inventaire[2])# Affiche : bouclier
Exemple 2 : Modifier un élément
# Pour remplacer l'objet à l'indice 3inventaire[3]="diamant"print(inventaire[3])# Affiche : diamant
Exemple 3 : Échanger deux éléments
# Pour échanger les éléments aux indices 1 et 5temp=inventaire[1]inventaire[1]=inventaire[5]inventaire[5]=temp
Questions :
Affichez l’objet situé à l’emplacement 4 de l’inventaire.
Le joueur ramasse un “parchemin”. Remplacez le premier emplacement “vide” par “parchemin”.
Le joueur utilise sa potion (indice 1). Remplacez-la par “vide”.
Échangez les objets aux emplacements 0 et 6 (épée et arc).
Créer une fonction echange qui prend une liste L ainsi que 2 indices i et j pour paramètres, et qui modifie la liste L en permutant les objets aux rangs i et j. Cette fonction n’aura pas de valeur de retour.
Ecrire l’instruction qui échange les objets aux emplacements 0 et 6, mais cette fois-ci, en utilisant la fonction echange.
Exercice 1.2 : Thermomètre intelligent
Un thermomètre enregistre les températures de chaque heure de la journée (24 valeurs).
# Pour calculer l'écart entre deux températuresecart=temperatures[10]-temperatures[3]print("L'écart est de",ecart,"degrés")
Exemple : Augmenter une valeur
# Pour augmenter de 3 degrés la température à l'indice 5temperatures[5]=temperatures[5]+3# ou plus court :temperatures[5]+=3
Questions :
Affichez la température à 14h (indice 14).
Une erreur de capteur s’est produite à 8h. Modifiez la valeur à l’indice 8 pour la remplacer par 16.
Pourrait-on utiliser la fonction echange? Si oui, écrire l’instruction correspondante.
Calculez l’écart entre la température maximale (indice 13) et minimale (indice 5).
Augmentez de 2 degrés la température de minuit (indice 0).
Partie 2 : Tableaux 1D - Parcours par élément et par indice
Exercice 2.1 : Analyse d’une partie de Scrabble
Un joueur de Scrabble possède les lettres suivantes dans son chevalet :
chevalet=['A','E','R','T','I','N','S']
Exemple 1: Parcours par élément
# Afficher chaque lettreforlettreinchevalet:print(lettre)
Exemple 2: Compter des éléments
# Compter les 'E' dans le chevaletcompteur=0forlettreinchevalet:iflettre=='E':compteur+=1print("Il y a",compteur,"lettre E")
Exemple 3: Vérifier une condition
# Vérifier si le chevalet contient un 'A'if'A'inchevalet:print("Il y a un A !")else:print("Pas de A")
Questions avec parcours par élément :
Affichez toutes les lettres du chevalet, une par ligne, en utilisant une boucle for lettre in chevalet.
Comptez combien de voyelles (A, E, I, O, U, Y) se trouvent dans le chevalet.
Affichez “BINGO!” si le chevalet contient au moins une lettre ‘S’, sinon affichez “Pas de S”.
Ecrire une fonction compte qui prend une liste L ainsi qu’une lettre V en paramètre, et qui retourne le nombre de fois où cette lettre est présente dans la liste.
Ecrire l’instruction qui appelle cette fonction pour déterminer le nombre de E dans le chevalet ['A', 'E', 'R', 'T', 'I', 'N', 'S']
Exercice 2.2: Parcours par indice
Exemple 1: afficher l’indice et l’élément
# Afficher chaque lettre avec sa positionforiinrange(len(chevalet)):print("Position",i,":",chevalet[i])
Exemple 2: Modifier en parcourant
# Remplacer tous les 'A' par des '*'foriinrange(len(chevalet)):ifchevalet[i]=='A':chevalet[i]='*'
Exemple 3: Créer un nouveau tableau
# Créer un tableau avec uniquement les voyellesvoyelles_trouvees=[]foriinrange(len(chevalet)):ifchevalet[i]in['A','E','I','O','U','Y']:voyelles_trouvees.append(chevalet[i])print(voyelles_trouvees)
Questions avec parcours par indice :
Affichez chaque lettre avec sa position : “Position 0 : A”, “Position 1 : E”, etc.
Remplacez toutes les voyelles par des ‘*’ en parcourant le tableau par indice.
Créez un nouveau tableau contenant uniquement les consonnes en utilisant les indices.
Partie 3 : Tableaux 2D - Parcours par élément et par indice
Exercice 3.1 : Grille de Morpion
Parcours par élément
Une grille de morpion est représentée par un tableau 2D de 3×3 :
forligneinmorpion:forcaseinligne:print(case,end=' ')print()# retour à la ligne# Affiche toutes les valeurs ligne par ligne:X|O|X|O|X||||O|
Exemple 2: Compter les éléments
# Compter les 'X'compteur=0forligneinmorpion:forcaseinligne:ifcase=='X':compteur+=1print("Nombre de X :",compteur)
Questions:
Affichez tous les ‘X’ de la grille, ligne par ligne en utilisant deux boucles for.
Comptez le nombre de cases vides (contenant ’ ‘).
Déterminez qui a le plus de coups joués (X ou O).
parcours par indice :
Exemple 1: Parcours par indice (tableau 2D)
# Afficher la grille avec les indicesforiinrange(len(morpion)):forjinrange(len(morpion[i])):print(morpion[i][j],end=' ')print()
Exemple 2: Accéder à un élément précis
# Afficher et modifier un élémentprint("Case [0][1] :",morpion[0][1])# Affiche 'O'morpion[0][1]='X'# Modifier la case
Exemple 3: Vérifier une ligne
# Vérifier si la ligne 0 contient trois symboles identiquesligne=morpion[0]ifligne[0]==ligne[1]==ligne[2]andligne[0]!=' ':print("La ligne 0 est gagnante !")
Questions:
Le joueur O joue en position [1][2] (ligne 1, colonne 2). Ecrire l’instruction qui modifie la grille.
Quelles sont les coordonnées morpion[i][j] pour chacune des cases? Dessinez sur votre cahier une matrice pour placer les coordonnées [i][j]dans chaque case..
Ecrire les instructions qui verifient si la première ligne contient trois symboles identiques (condition de victoire).
Ecrire une fonction ligne_X qui prend pour paramètre une matrice M comme la grille de morpion (3*3). M contient dans chaque case 'X', 'O', ou ''. Cette fonction retournera True si l’une des lignes est remplie avec trois 'X'.
Exercice 3.2 : Grille de Sudoku (9×9)
Voici une grille de Sudoku partiellement remplie :
# Compter les 0 dans toute la grillecompteur=0foriinrange(len(sudoku)):forjinrange(len(sudoku[i])):ifsudoku[i][j]==0:compteur+=1print("Nombre de cases vides :",compteur)
Exemple : Afficher une ligne
# Afficher la ligne 0forjinrange(len(sudoku[0])):print(sudoku[0][j],end=' ')print()
Exemple : Afficher une colonne
# Afficher la colonne 2foriinrange(len(sudoku)):print(sudoku[i][2],end=' ')print()
Exemple : Modifier une case
# Remplacer le 0 en position [0][2] par 4sudoku[0][2]=4print("Nouvelle valeur :",sudoku[0][2])
Exemple : Extraire un bloc 3×3
# Extraire le bloc en haut à gauche (lignes 0-2, colonnes 0-2)bloc=[]foriinrange(0,3):# lignes 0, 1, 2ligne_bloc=[]forjinrange(0,3):# colonnes 0, 1, 2ligne_bloc.append(sudoku[i][j])bloc.append(ligne_bloc)print(bloc)
Exemple : Vérifier les doublons dans une ligne
# Vérifier si la ligne 1 contient des doublons (sans compter les 0)ligne=sudoku[1]nombres=[]forvaleurinligne:ifvaleur!=0:ifvaleurinnombres:print("Doublon détecté !")else:nombres.append(valeur)
Questions avec parcours par indice :
Comptez le nombre de cases vides (valeur 0) dans toute la grille.
Affichez tous les chiffres de la première ligne (ligne d’indice 0).
Affichez tous les chiffres de la cinquième colonne (colonne d’indice 4).
Remplacez le 0 en position [0][2] par le chiffre 4.
Ecrire une fonction doublons, qui prend en paramètre une grille de sudoku G, ainsi qu’un numero de ligne i, et qui retourne un booléen True/False. selon si la ligne i contient des doublons. (sans compter les 0).
Appeler la fonction doublons pour vérifier si la première ligne contient des doublons.
Créez une fonction bloc qui extrait l’un des 9 blocs 3×3, n’importe où dans la grille. (par exemple, le bloc en haut à gauche : lignes 0-2, colonnes 0-2), à partir des indices i,j de départ (coin supérieur gauche du bloc).
Conseils généraux
Testez votre code progressivement : ne cherchez pas à tout résoudre d’un coup.
Utilisez des fonctions pour organiser votre code et le rendre réutilisable.
Affichez des résultats intermédiaires avec print() pour vérifier votre logique.
N’oubliez pas : les indices commencent à 0 en Python !
Le jeu du Morpion est un jeu de réflexion se pratiquant à deux joueurs au tour par tour et dont le but est de créer le premier un alignement sur une grille (3x3).
Vous allez programmer le jeu du Morpion contre l’ordinateur. L’ordinateur devra repondre à chacun des coups du joueur et, si possible, remporter la partie.
Pour traiter ce projet, il est fortement recommandé de bien maitriser l’exercice 3.1, vues dans le TD sur les tableaux.
Afin d’analyser la partie, et prevoir les prochains coups à jouer, l’ordinateur utilisera les fonctions suivantes, que vous devrez programmer:
compteur
victoire
cherche_car
Prévoir ensuite le prochain coup à partir des informations fournies, et créez un jeu, où l’ordinateur ne sera jamais perdant.
Compteur du nombre de caractères identiques
Lire et tester le programme suivant:
Exemple: Compte le nombre de X dans une ligne, colonne ou diagonale
# Vérifier si la ligne 0 contient trois symboles identiquesliste_X=[0,0,0]liste_Y=[0,1,2]compteur=0foriinrange(len(liste_X)):x=liste_X[i]y=liste_Y[i]ifmorpion[x][y]=='X':compteur+=1print("il y a ",compteur,"cases X dans la ligne 0")
Dans la boucle for, l’indice i varie de 0 à 2.
Pour i=0, x a pour valeur liste_X[0] -> 0 et y a pour valeur liste_Y[0] -> 0. Le couple x,y vaut alors 0,0.
On utilise ces coordonnées pour relever le symbole de la case morpion[0][0]. C’est un X. On augmente alors le compteur d’une unité (on compte les X).
On continue dans la boucle for avec les cases 0,1 puis 0,2.
Etape 1: Créer une fonction compteur qui prend une grille, un caractère car, une liste liste_X et une liste liste_Y en paramètres. Cette fonction devra retourner le nombre de fois que ce caractère car apparait.
Exemple: utiliser la fonction compteur
# Etape 1morpion=[['X','O','X'],['O','X',' '],[' ','O','O']]defcompteur(grille,car,liste_X,liste_Y):c=0foriinrange(len(liste_X)):# à completer x=...y=...ifgrille[][]...c=c+...returnccompteur(morpion,'X',[0,0,0],[0,1,2])# retourne:2
premiere étape de la boucle for
La fonction retourne 2: à la premiere ligne, il y a bien 2 caractères ‘X’.
Utilisez votre fonction
Etape 2: utilisez votre fonction pour déterminer le nombre de ‘X’ dans chacune des lignes, dans chacune des colonnes, et dans chacune des diagonales (8 appels de la fonction). Placer chaque valeur dans une liste L, puis afficher celle-ci.
# Etape 2L=[]L.append(compteur(morpion,'X',[0,0,0],[0,1,2]))L.append(compteur(......print(L)
Victoire
Etape 3: Créer une fonction victoire, qui prend une grille de morpion en paramètre, ainsi qu’un caractère car (qui vaut X ou O), et vérifie si la condition de victoire est réalisée pour le joueur X ou O. La fonction retournera un booléen True/False.
Exemple: Victoire des X
# Etape 3morpion=[['X','O','X'],['O','X',' '],[' ','O','X']]defvictoire(grille,car):b1=compteur(grille,car,[0,0,0],[0,1,2])b2=compteur(grille,car,[1,1,1],[0,1,2])# a completerb8=compteur(grille,...)returnb1==3or...victoire(morpion,'X')# retourne:Truevictoire(morpion,'O')# retourne:False
Interface joueurs
Etape 4: Vous allez maintenant programmer l’interface joueurs, en demandant alternativement, à chacun d’entre eux les coordonnées x,y pour placer son pion: ‘X’ puis ‘O’, puis ‘X’, puis ‘O’, …
# Etape 4Fin_de_partie=Falsewhilenotvictoire(morpion,'X')andnotvictoire(morpion,'O')andnotFin_de_partie:afficher(morpion)print('Joueur X:')x=int(input("jouer à la ligne (0,1,2), 3=Fin: "))y=int(..)...
Puis…
Si le joueur ‘X’ n’est pas vainqueur, demander à l’adversaire où il veut jouer.
Le joueur ‘O’ est-il gagnant?
Afficher la grille modifiée après ce tour de jeu
Recommencer s’il n’y a pas de vainqueur.
Phase 2: Comment jouer contre l’ordinateur?
Dans cette phase du projet, nous allons remplacer les choix du joueur ‘O’ par ceux de l’ordinateur. Ce sera lui qui essaiera de vous bloquer lorsque vous avez deux pions ‘X’ alignés, et que vous risquez de gagner à la partie suivante.
Nous aurons besoin de 2 nouvelles fonctions:
cherche_car: fonction qui recherche la première case vide dans un ensemble de cases du morpion, et retourne les coordonnées x,y de cette case
jeu_de_defense: qui retourne les coordonnées x,y de la case qui doit bloquer le joueur (si celui-ci a une ligne avec deux ‘X’ et peut gagner au prochain tour)
Detection case vide
Etape 1: Ecrire une fonction cherche_car(grille,car,liste_X,liste_Y) qui verifie si les cases de coordonnées (liste_X[0], liste_Y[0]), (liste_X[1], liste_Y[1]), (liste_X[2], liste_Y[2]) contiennent au moins un symbole car, et retourne les coordonnées de la première case contenant le caractère car.
Exemple: recherche d’un espace ’ ’ dans la ligne 2
# Etape 1morpion=[['X','O','X'],['O','X',' '],[' ','O','O']]defcherche_car(grille,car,liste_X,liste_Y):foriinrange(len(liste_X)):x=liste_X[..y=liste_Y[..ifgrille[..][..]==...:returnx,ycherche_car(morpion,' ',[2,2,2],[0,1,2])# retourne:(2,0)
La fonction retourne (2,0), car à la case de coordonnées [2][0], il y a un symbole ' '.
recherche d'un caractère espace ' ' dans la dernière ligne
Exemple: recherche du premier espace ’ ’ dans tout la grille
Lorsque l’on recherche un caractère dans TOUTE la grille, il y a 9 coordonnées à renseigner pour chacune des listes.
Etape 2: créer une fonction jeu_de_defense, qui prend pour paramètre grille, et car_attaquant, qui vaudra ‘X’ ou ‘O’.
Cette fonction va permettre de programmer le jeu complet, pour jouer contre l’ordinateur.
Pour chacune des lignes, puis pour chacune des colonnes, et enfin chaque diagonale:
Si la ligne contient 2 caractères ‘X’ (fonction compteur, et que la ligne contient un espace (cherche_car ne retourne pas None), alors retourner les coordonnées x,y retournées par la fonction cherche_car.
Sinon, retourner None
defjeu_de_defense(grille,car_attaquant):ifcompteur(grille,car_attaquant,[0,0,0],[0,1,2])==2andcherche_car(grille,' ',[0,0,0],[0,1,2])!=None:# jouer dans une case vide de la ligne 0jouer_case=cherche_car(grille,' ',[0,0,0],[0,1,2])elifcompteur(grille,car_attaquant,[1,1,1],[0,1,2])==2andcherche_car(grille,' ',[1,1,1],[0,1,2])!=None:# jouer dans une case vide de la ligne 1jouer_case=cherche_car(grille,' ',[1,1,1],[0,1,2])elif(...)(...)elifcompteur(grille,car_attaquant,[0,1,2],[0,0,0])==2andcherche_car(grille,' ',[0,1,2],[0,0,0])!=None:# jouer dans une case vide de la colonne 0jouer_case=cherche_car(grille,' ',[0,1,2],[0,0,0])(...)else:jouer_case=Nonereturnjouer_case
Pour appeler la fonction, et bloquer l’adversaire ‘X’, faire:
Ainsi, si aucune des lignes, colonnes, diagonale ne correspond ne contient deux caratères ‘X’ alignés, retourner la premiers case vide trouvée dans la grille: ce sera l’emplacement où l’ordinateur ‘O’ peut jouer.
Pour cette dernière phase du projet, vous pourrez télécharger le script python contenant toutes les fonctions nécéssaires: telecharger
Pour élaborer une stratégie plus avancée de l’ordinateur, on pourra consulter la page dédiée: site tictactoe.com
site TICTACTOEFREE.COM
pour jouer contre l’ORDINATEUR. (utiliser la fonction jeu_de_defense pour prevoir la case dans laquelle il devra jouer).
Organisez au mieux votre script. Commentez vos fonctions.
Pour les élèves de Terminale:
Prévoir et anticiper toutes les erreurs possibles de saisie du joueur, tous les defauts possibles qui peuvent survenir dans la partie (plus de O que de X, erreurs avec les coordonnées saisies, terminaison de la boucle while, …). On pourra ajouter des structures conditionnelles supplémentaires, ou bien des tests d’assertion, ou autres mécanismes. (try.. except, raise,…): Voir cours sur la mise au poin d’un programme: python avancé
Utiliser une structure de données Pile pour permettre un retour en arriere (le joueur efface ses coups précédents).
Projet de fin de séquence: créer une campagne de sensibilisation (affiche + post type Instagram/TikTok fictif) sur un enjeu réel : cyberharcèlement, désinformation, addiction au scroll, ou effet de bulle de filtre. Justifier le choix (ciblage, algorithme de recommandation, mécanismes d’engagement) en s’appuyant sur ce qui a été vu en cours. Variante plus technique : concevoir le cahier des charges d’un “réseau social idéal pour lycéens” en explicitant les paramètres de confidentialité et leurs compromis. reseaux sociaux
identité numérique, modélisation des liens d’amitié, aspects economiques et sociaux
Projet de fin de séquence: créer un mini-site HTML/CSS de 3-4 pages sur un sujet de son choix, avec navigation, liens hypertexte, structuration correcte (balises sémantiques). une “enquête” sur un site réel (certificat HTTPS, mentions légales, cookies) restituée sous forme de fiche d’analyse. le web
definition du web, navigation entre pages, moteur de recherche, URL
modele client serveur
modele client serveur et URL, securite et confidentialite
HTML
langage HTML, balises
introduction à CSS
declaration css, selecteur, propriete, valeur, heritage, arbre du DOM
Projet de fin de chapitre: Réaliser un traceroute/ping vers plusieurs sites (France, Europe, autre continent), relèver les adresses IP et temps de latence, puis produire un schéma annoté expliquant le trajet des paquets (routeurs, protocole TCP/IP, adressage). généralités
usage d’internet, les formes de communication
reseau local et reseau internet
machines et architecture reseau, liaisons entre machines, adresses MAC et adresses IP
circulation des données
protocoles, routage, modele client serveur, DNS, http et https, VPN
TP simulation d’un réseau
TP Filius, reseau a 2 machines et plus, adresses IP
Projet de fin de chapitre: conception d’un objet simple (arrosage automatique, alarme, feu tricolore) avec algorithme, capteurs et actionneurs identifiés. IOT
robot, machine et ordinateur, chaine d’information et d’energie, objet connecté
Programme informatique
programmer un robot, algorithme et langage informatique
Python Turtle
dessiner en donnant des ordres
Projet de fin de chapitre: comparer les tailles de fichier selon la résolution et le format (JPEG vs PNG), et documenter la perte de qualité liée à la compression. stéganographie (retrouver le message caché dans une image) créer une affiche démontant une image retouchée/deepfake avec analyse technique (pixels, métadonnées). Photographie numérique
appareil photographique numerique, codage, pixel, prise de vue
Enjeux ethiques et societaux de l’image
droit a l’image, propriete, fausses informations
EXIF et données colorimetriques
TP coloration, outil de prelevement de couleurs, code RGB des couleurs, et donnees EXIF, obtenue a partir d’una app en ligne
TP pixel art
TP python, tableaux, codage d’une image numerique, microbit
Projet de fin de chapitre: Organisation d’un rallye géolocalisé dans l’établissement. GPS services
geolocalisation sur un smartphone, reglages, confidentialité, calcul d’itineraires
geolocaliser
methode d’echolocation, trilateralisation
introduction aux graphes et internet
modelisation d’une carte numerique par un graphe
fonction de conversion TI83
utiliser les fonctions python pour convertir les unités des repères d’angle, version TI83
fonction de conversion android
utiliser les fonctions python pour convertir les unités des repères d’angle, version tablette android
Sous-sections de SNT
Donnees structurees
Projet de fin de chapitre: Enquêter sur les données de sondage: Lien
Le document suivant donne un aperçu des périodes d’existence d’anciennes civilisations.
L’apparition des grandes civilisations commence alors que le néolithique prend fin. C’est l’usage de la metallurgie qui aura pour conséquence de structurer davantage la société, avec l’usage d’armes en métal par des soldats spécialisés. La protection des richesses accumulées par les producteurs est confiée à des guerriers professionnels. La société se hiérarchise: timeline
Carte perforée. IREM Lille
La naissance de l’écriture… et du nombre
Dans les temps préhistoriques, les hommes ont eu besoin de recourir à une numération. Ils ont naturellement utilisé des artefacs pour compter (des objets, des os…). L’écriture n’existait pas.
Le plus vieux vestige montrant cette activité date de 35 000 ans. Il s’agit d’un os qui a été utilisé comme baton de comptage.
Le bâton d’Ishango (à gauche), exposé à l’Institut royal des sciences naturelles de Belgique
(source: PourlaScience.fr)
Que comptaient-ils exactement avec ce baton? Les proies tuées, le nombre d’individus de leur clan, …, il nous est impossible de le savoir.
Pour certains peuple primitifs, la numération se limitait d’ailleurs à 3 : un, deux, trois, beaucoup…
Au néolithique, la société devient sédentaire et se structure davantage. Alors l’homme éprouve un besoin plus urgent de dénombrer, et de calculer.
A partir du VII millénaire avant JC : des vestiges de jetons en pierre montrent l’activité de compter. D’autres objets de comptage ont été utilisés, comme des petits jetons en argile (calculis) que l’on mettait dans une bourse:
Il s’agissait d’une sphère d’argile creuse dans laquelle on insérait des calculis et sur laquelle on marquait le contenu et qu’on signait avec un sceau-cylindre.
Bulle-enveloppe et ses jetons de comptabilité (Institute museum Chicago)
Comment ça se passe en pratique, le dénombrement ?
Au quotidien, les hommes ont d’abord utilisé leurs doigts ou leur phalanges pour compter. Selon la méthode employée, ils ont alors compté en base 10 (10 doigts de la main), ou en base 20 (en incluant les doigts de pied), en base 12 (en utilisant les phalanges), ou en base 60.
Au IV millénaire avant JC : On trouve les plus anciennes traces de chiffres écrits (Mésopotamiens1 et Egyptiens), gravés sur des supports en argile.
Les symboles que l’on peut observer sur la photographie suivante sont des formes de clous ou des barres verticales |, des chevrons <.
tablette en argile. 3000 ajc. Mésopotamie
Les symboles des unités sont employés pour les chiffres de 1 à 9:
Ceux des dizaines: de 10 à 50 (1 à 5 dizaines):
Comment ces chiffres constituent-ils des nombres ?
Les systèmes de numération antiques variaient d’une aire culturelle à l’autre :
Pour chacun des systèmes de numération, la valeur d’un nombre est égale à la somme des symboles qui le composent. Ce sont des numérations dites additives.
Base 10:Les Egyptiens2, pour écrire le chiffre 7, répétaient le symbole de l’unité | sept fois par exemple ( ||||||| ). lorsque ces symboles devaient être répétés dix fois, on remplaçait ces 10 symboles unitaires par un nouveau symbole correspondant à la dizaine.
Il s’agit d’une numération en base 10 (numération décimale), mais différente de la notre: Un autre symbole correspond à la dizaine de dizaine, etc.
symboles utilisés par les egyptiens, de 1 à 1 million
Base 60: Pour les Babylonniens3 cependant, cette numération ne permettait de compter que jusqu’à 59. Ils ont alors utilisé les mêmes chiffres pour dénombrer les soixantaines:
$$71 = 1 \times 60 + 11 \times 1$$
Ce qui s’écrira en notation babylonienne:
$$| ~ >|$$
Equivalence entre la base 60 sumérienne et notre base décimale
Toutes les civilisations n’ont pas adopté la numération décimale, ni les mêmes symboles pour compter :
Les Sumériens au proche-orient comptaient en base 60 (numération sexagésimale).
La base 12 (système duodécimal) était connue et utilisée par certaines populations (Moyen-Orient, Roumanie, Égypte, etc.)
En Eurasie, les peuples indo-européens utilisaient un système décimal mais avec des symboles alphabétiques, notamment par les signes I, V, X, L, C, D et M, appelés chiffres romains: voir article et exemples4
symboles romains
Comment est apparu le ZERO ?
Les Sumériens ont progressivement remplacé les petits objets en argile représentant les nombres par l’écriture sur des tablettes en argiles. Ils gravaient dessus avec un calame en roseau. Le comptage matériel est alors devenu un comptage conceptuel. Ainsi sont nés les plus vieux chiffres connus de l’histoire, et surtout, l’invention du ZERO.
Sans l’écriture du zero, il peut y avoir une confusion dans la lecture. Le nombre suivant, écrit en notation babylonienne :
$$| > |$$
Celui-ci peut ainsi signifier:
$$1 \times 60 + 11 \times 1 = 71$$
mais aussi, selon la position supposée de l’espacement:
L’invention du ZERO implique que l’écriture du nombre va suivre la règle de la position des symboles : les dizaines sont écrites avec un symbole mis à la position des dizaines, les unités sont écrites avec un symbole mis à la position des unités. Et lorsque le nombre par exemple ne comporte pas de dizaine, on met un ZERO à la position du chiffre des dizaines.
C’est la position du chiffre qui permet de savoir si celui-ci représente unité, dizaine ou centaine. C’est ce que l’on appelle la numération de POSITION.
Ce signe signifiant RIEN, et appelé le ZERO sera décisif pour l’apparition de la science du calcul, l’arithmétique.
Sans l’écriture du ZERO, l’usage des nombres ne permet pas de réaliser facilement des opérations. On ne peut pas facilement reporter des retenues depuis les unités vers les dizaines par exemple (base 10). Le zero va faciliter les opérations arithmétiques.
Fondamentalement, ce sont les savants indiens qui vont faire évoluer le zéro vers le sens que nous lui reconnaissons aujourd’hui, à savoir d’un nombre entier non naturel, pair, ni premier, ni positif, ni négatif.
video Futura Sciences : Les découvertes du zero
Epoque médievale
Le savoir circule à travers le monde de l’Extrême-Orient à l’Egypte, de la Méditerranée à l’lslande.
Au IXe siècle, les Arabes emprunteront aux Indiens le zéro, le mot sunya devenant sifr. Ce ne sera finalement qu’au XIIe siècle que cette écriture arrivera en Occident, issue des « Ghubâr », les arabes occidentaux.
Les Égyptiens de l’Antiquité utilisaient des hiéroglyphes pour écrire leurs nombres. Ce système de hiéroglyphes est assez proche de notre système de numération décimale : chaque symbole possède une valeur (1,10,100,1 000…) et peut être écrit jusqu’à neuf fois.
En étudiant les trois exemples donnés ci-dessous, retrouver la valeur des sept hiéroglyphes utilisés. (voir images)
Comment les egyptiens écrivaient-ils le nombre 1637 ?
Comparer les numérations Babylonienne et Egyptienne : laquelle des deux est une numération de position ? Justifiez.
Les egyptiens, avaient-il une manière de représenter les fractions de 1 (par exemple 1/2)? Expliquer.
La numération maya est une numération de base vingt pratiquée dans la civilisation mésoaméricaine maya.
Pour écrire les petits nombres, par exemple la durée d’une lunaison (c’est-à-dire les entiers 29 ou 30) ou les petits déplacements (dans l’almanach divinatoire de 260 jours), les Mayas disposaient d’une numération de type additif utilisant trois signes pour 1, 5 et 20 ; dans cette écriture : ‘20,9’ s’interprète 20 + 9. On trouve ainsi le nombre 62 écrit à l’aide de 3 signes « 20 » complétés de 2 points … (wikipedia).
L’écriture d’un nombre se fait par empilement de chiffres. Chaque étage correspond à un poids 20 fois supérieur au poids de l’étage inférieur, à l’exception du passage du 2e au 3e étage où la multiplication n’est que de 18. Ainsi la valeur de l’étage le plus bas est multipliée par 1, du second étage par 20, du troisième étage par 20 × 18 = 360
LeMonde Histoire
Les Mayas, utilisaient-ils l’écriture pour représenter les nombres? Si oui, sur quel support écrivaient-ils?
S’agit-il d’une numération de position?
Commenter le document ci-dessus et expliquer cette numération.
Quelle est la valeur de la base de la numération binaire?
Sans effectuer de calcul, dire si le nombre binaire 10011001 est pair ou impair.
Quelle est la valeur la plus élevée que l’on peut écrire avec 8 symboles, en notation binaire?
Comment écrit-on le nombre 1637 en binaire?
Citer un ou des avantages de la notation binaire.
Le binaire est aussi utilisé pour écrire des lettres et des caractères. Comment?
Additionnez 1010 (binaire) + 1101 (binaire), réponse en binaire. Expliquez la procédure.
Numération Hexadécimale
Quelle est la valeur de la base de la numération hexadécimale?
L’écriture #F4 représente t-elle un nombre héxadecimal? Si oui, quelle est sa valeur?
Quelle est la valeur la plus élevée que l’on peut écrire avec 2 symboles, en notation hexadécimale?
Comment écrit-on le nombre 1637 en hexadecimal?
Citer un ou des avantages de la notation hexadécimale.
L’hexadécimal est aussi utilisé pour écrire des lettres et des caractères. Comment?
Comment convertir rapidement 1100 1001 (binaire) en héxadecimal?
Le système bibinaire
Le chanteur et mathématicien Boby Lapointe, surtout connu pour ses talents d’auteur, de compositeur et d’acteur, a inventé un système de numération qu’il voulait universel et proche
du langage des ordinateurs. Ce système, qualifié de bibinaire, s’appuie sur l’écriture binaire des nombres et présente deux aspects, un langage écrit qui repose sur des symboles associés aux nombres, et un langage oral.
Soit un nombre N. Par exemple : N = 347, donc N = 101011011 (binaire).
Dans le système bibinaire, on décompose l’écriture binaire en quartets (groupements de quatre bits) en partant de la droite et en ajoutant à gauche, si besoin est, les zéros complémentaires pour former un nombre entier de quartets.
Ici, N = (0001 0101 1011).
On considère que chaque quartet est composé de deux duets (00, 01, 10 ou 11). A chaque duet est associé une consone ou une voyelle, selon que ce duet est en tête ou en queue du quartet :
Duet
Correspondance duet de tête
Correspondance en duet de queue
00
H
O
01
B
A
10
K
E
11
D
I
Ainsi, le quartet 0111 se lit BI, car 01 est en tête et correspond à B et 11 est en queue et correspond à I.
Le nombre N = 347 après écriture binaire, se lit HABAKI.
Combien de quartes différents peut-on écrire en numération binaire ?
Quelle est la base réellement utilisée dans le système bibinaire ?
Quels nombres décimaux correspondent aux mots : HEKAKA, BOKEKE, KEBOBO et KEBAHI ?
Comment sont traduits les nombres 52326 et 11847 dans le langage bibinaire?
Notes
Mésopotamiens : La civilisation babylonienne est héritière de Sumer, et elle s’est épanouie en Mésopotamie du Sud du début du IIe millénaire av. J.-C. jusqu’au début de notre ère. Elle est marquée par l’affirmation progressive, de la cité de Babylone, capitale de l’État qui connait son apogée à partir du VIe siècle av. J.-C. Cette cité prospère étend son influence du nord-est de la Syrie, au nord de l’Irak actuel, ainsi que les plaines plus au sud. Les milliers de tablettes cunéiformes découvertes sur les différents sites de Babylonie (Babylone, Ur, Uruk, Nippur, Sippar, etc.) ont permis de dresser le tableau d’une civilisation urbaine reposant sur une agriculture irriguée potentiellement très productive. https://fr.wikipedia.org/wiki/Babylone↩︎
Les machines ne comprennent que les chiffres ! Et pas n’importe lesquels : 0 et 1 sont ses préférés… Pourtant, une machine comme celle qui vous sert à afficher cette page n’est pas (seulement) une calculatrice:
Comment peut-on travailler avec du texte ou des images sur une machine, qui ne manipule que du binaire?
Mémoire d’une machine
Une machine manipule des données numériques BINAIRES. Ce sont des nombres constitués de chiffres ne pouvant prendre que 2 valeurs, 0 ou 1 : des bits.
Le stockage des bits s’est fait autrefois sur support papier (avec/sans trou):
carte perforée IBM - source wikipedia
source - courstechinfo.be/Techno/Historique2.html
Une machine comme l’IBM 1401 lisait les cartes (a) pour en recopier le code sur une bande magnétique (b). Un gros calculateur lisait cette bande (c), exécutait les jobs (d) puis transcrivait les résultats sur une autre bande (e) postposant ainsi l’impression des résultats (impression off-line) faite ensuite par un ordinateur plus léger (f).
On devine en quoi les machines ont grandement evolué: aujourd’hui, le processeur gère tout seul l’accès aux données et aux programmes. Il n’y a plus besoin d’un personnel humain…
Mais alors, comment représenter et organiser les données sur un support (mémoire) pour qu’elles soient accessibles (lecture/ecriture) par le processeur ?
Aujourd’hui, le support mémoire est constitué de milliards de transistors, possédant 2 niveaux de tension : 5V ou 0V.
C’est donc le transistor qui permet la représentation d’un bit de donnée, en ajustant la tension électrique au niveau haut ou au niveau bas.
Le transistor: un composant électronique à 2 états
Le nombre de transistors sur une puce électronique devrait être doublé tous les 2 ans, pour le même prix de fabrication. Les transistors deviennent donc de plus en plus petits.
La figure suivante montre l’évolution du nombre de transistors pour un même élement de surface:
illustration de la loi de Moore - source wikipedia
Les transistors sont gravés sur circuits intégrés, ce qui a permi d’atteindre des fortes densités par unité de surface. La finesse de gravure est actuellement de 10 nm environ (Intel).
Le transistor: un composant électronique à 2 états
Une machine va traiter des informations qui vont être à l’origine très diverses, plus ou moins structurées, mais toujours en binaire :
Ce sont des nombres, des caractères, des mots, des images, des sons, des bruits, la température, la quantité d’argent qu’on a dans notre porte-monnaie, notre âge, des dates, etc.
La quantité de mémoire, même importante, n’est pas infinie dans une machine. C’est pourquoi on doit reserver un certain nombre de bit à chaque donnée, et ce nombre doit être ajusté au mieux.
Pour coder une information qui peut prendre plus de 2 valeurs, il faudra utiliser plusieurs bits. Ceux-ci sont souvent rassemblés par 8, formant un mot-octet. Celui-ci peut prendre 256 valeurs.
Stocker de manière durable: Disque dur
Les mémoires se partagent en 2 familles: Les mémoires volatiles, comme la RAM: les données stockées vont s’éffacer lorsque l’on coupe l’alimentation de la machine. Et les mémoire persistantes, pour lesquelles les données ne s’effacent pas lors de la mise hors tension.
Le disque dur est du 2e type. Il utilise des pistes magnétiques sur un plateau pour écrire et lire avec une tête magnétique.
disque dur - Wikipedia
Actuellement, les disques durs vendus dans le commerce contiennent 1 à plusieurs To (teraoctets: 1015 octets)
Numériser des données - les standards internationaux
Dès l’invention de l’informatique, les ordinateurs ont pu manipuler des textes composés de caractères, que ce soit pour la saisie des commandes sur un clavier ou pour l’impression des résultats sur le papier. Il a donc fallu adopter une convention commune qui soit utilisée par tous les ordinateurs. Ainsi, est né en 1961 le code ASCII (American Standard Code for Information Interchange) qui associe une valeur numérique à chaque caractère de l’alphabet : 65 pour A, 66 pour B…
table ascii, source: lookuptable.com
Avec la taille des mémoires, et les performances des machines qui ont progressé, il a été possible de coder des données de plus en plus complexes. Il a fallu trouver un moyen de structurer ces données, c’est à dire de les mettre en forme et en lien dans un format approprié.
TP4 Formulaire d’enquête, conception du formulaire pdf et traitement Lien
Introduction
En informatique, tout est donné, depuis les 0 et les 1 qui décrivent l’état des transistors dans un circuit électronique, jusqu’à une vidéo, en passant par les photos, les adresses, un relevé de température ou l’âge d’une personne. Les données sont souvent rassemblées pour caractériser un objet comme l’adresse d’une personne (composée du numéro de rue, du nom de la rue, du code postal, de la ville et du pays par exemple). Lorsque les données sont ainsi rassemblées pour décrire quelque chose avec plusieurs informations, on parle de données structurées (voir plus loin).
activité sur le traitement des données
A partir de l’image projetée, choisir une méthode pour placer les informations dans un même tableau. Quelles seront les étiquettes de colonne?
Lorsque l’on place ses données sur une page internet, les champs du formulaire demandent un format particulier pour les données. Etes vous capables de retrouver rapidement l’information suivante: quel évènement a pour plaignant Me Dubois? => besoin de ranger les informations dans une table pour effectuer la recherche avec une clé (étiquette de colonne)
Ouvrir la page de l’activité. Recopier le tableau et le compléter avec 3 étiquettes post-it ou plus. (consigne précise: Votre mission est d’extraire les informations importantes et de les organiser dans le tableau fourni ci-dessous.)
Type de variable, cellule d’un tableur
Selon la mise en forme, le format associé est soit du texte (entre guillemets, soit un nombre (virgule pour décimal), mais cela peut être aussi une date (15/09/2023), une heure (8:30) ou une coordonnée GPS exprimée en degré minute d’arc seconde (45°30’45’’).
Dans un fichier .xls, ou csv, les données sont structurées. Dans une même colonne, les données sont dans le même format (sont du même type)
Présentation des données
Un fichier Excel regroupe une ou plusieurs table(s)
Dans une table, les données sont mises dans des colonnes, où elles ont le meme type.
Chaque donnée est dans une cellule, référencée par ses coordonnées.
Chaque TABLE représente une COLLECTION. C’est à dire un ensemble d’objets (des lignes) qui partagent les mêmes DESCRIPTEURS. Les valeurs de ces objets ont un certain type. Chaque colonne contient des valeurs du même type.
Chaque ligne contient une information.
Open datas et données structurées
video du site cookie-connecté
L’open data (ou données ouvertes) est l’ouverture via le Web de données collectées par des organismes publics (ou entreprises), et dont la diffusion est considerée comme d’interêt général.
Quelques exemples:
horaires transports publics
état des lignes (métro, autobus…)
prévisions météorologiques
prix des carburants
…
Il y a des conditions à respecter pour la mise à disposision de ces données. Une donnée doit être de nature:
ouverte
primaire
libre de droit
Organisation des données
Une collection de données peut être ordonnée sous forme de liste, ou d’une table.
La façon de structurer les données influe fortement sur les opérations de traitement : il est par exemple bien plus efficace de rechercher une donnée dans une collection toujours ordonnée, mais y insérer une information est plus coûteux.
Donnée : représentation d’une information au sein d’un système informatique.
Métadonnée : donnée servant à définir ou décrire une autre donnée, pour permettre sa manipulation.
Une base de données regroupe plusieurs collections de données reliées entre elles.
Descripteur : mot ou un groupe de mots choisi pour caractériser les informations contenues dans un document et pour faciliter les recherches.
Une collection regroupe des objets partageant les mêmes descripteurs (par exemple, la collection des contacts d’un carnet d’adresses). La structure de table permet de présenter une collection : les objets en ligne, les descripteurs en colonne et les données à l’intersection. Les données sont alors dites structurées.
Une information est issu du croisement de plusieurs données. On donne un nouveau sens à ces données.
Format des données
L’OPen Datas exige que les données doivent être au format EXPLOITABLE, et non proprietaire.
Souvent, on va trouver les format csv, json et XML pour les fichiers.
csv:
nom, prenom, age
Dupont, François, 17
Darcis, Pauline, 16
Plateforme ouverte des données publiques françaises
Le Répertoire National des Élus (RNE) a pour finalité le suivi des titulaires d’un mandat électoral. Il est renseigné et tenu à jour par les préfectures et hauts commissariats et par les services du ministère de l’intérieur, notamment sur la base des éléments fournis par les élus lors de la phase d’enregistrement des candidatures.
Données du RNE pour les conseillers municipaux - extrait en csv
Les données du RNE sont structurées par mandat. Neuf fichiers sont publiés ici :
les membres des assemblées des collectivités à statut particulier ;
les représentants au Parlement européen ;
les sénateurs ;
les députés ;
les maires.
En bas de page, vous pourrez observer les réutilisations de ces documents:
exemples de réutilisation des données ouvertes sur les elus municipaux
On voit ici comment des données numériques sont transformées en informations.
Ouvrir les données jugées d’intérêt public, c’est encourager leur réutilisation par tout un chacun. Cela permet d’encourager la transparence démocratique, de bénéficier de services au quotidien ou de prendre des décisions plus éclairées.
TP4 Formulaire d’enquête, conception du formulaire pdf et traitement Lien
Activité 1: Trouver une information
Lea, une jeune mère de famille a accepté l’enregistrement de ses données de géolocalisation par le service Google.
Elle se renseigne sur les données enregistrées et obtient le tableau suivant pour les jours 15/09 et 16/09:
Quelle est la référence de la case contenant la valeur 08:45 ? …
Quelle est la valeur de la case E4 ? …
Compléter la formule de calcul de la distance parcourue le 15/09:
= E4 + …
Compléter la formule utilisant la fonction somme pour calculer la distance totale parcourue pendant ces 2 jours:
= SOMME(E4 : …
D’après les données de ce tableau:
Quelle a été la journée de Lea le Dimanche 15/09?
Où est le lieu de travail de Léa?
Activité 2: Données en plusieurs tables
L’agence de voyage Globe Trotteur enregistre les données de ses clients sous la forme de plusieurs tables: CLIENTS, VOYAGES et VOLS:
Quel est l’identifiant de Julien Dumas dans le fichier CLIENTS?
Quelles étaient les destinations de Francoise Dargent au cours du mois d’octobre 2024?
Combien de miles cela lui-a-t-il rapporté dans son programme de fidélité?
Chaque traitement sur la base de données s’exprime de la manière suivante:
Rechercher dans la colonne … de la table … la valeur … et retourner la valeur de la colonne …
ou bien:
Filtrer les lignes de la table … en conservant celles où la colonne … vaut …
Dans la table … faire la somme des valeurs de la colonne …
On peut aussi réaliser une combinaison de ces 3 opérations: par exemple, faire la somme sur les colonnes d’un tableau filtré.
Pour chacune des 3 premières questions, énoncer le traitement qui est réalisé.
Trouver une information à laquelle la base de données peut répondre. Formuler la question, comme vu dans les questions 1. à 3.
Cours
Recherche et tri
Le traitement sur des données structurées peut consister à:
rechercher une donnée (critère)
filtrer sur les données selon un critère
La formule exprime alors une idée du type: sur le tableau de données T, je cherche la valeur couleur correspondant à la fréquence 4,19
Calculer
Pour copier une donnée dans une nouvelle cellule, on peut faire une copie par référence en indiquant sa coordonnées, après le signe =
Le traitement peut aussi consister à réaliser des calculs:
= somme(E4:E11)
= E4 + E5 + E6
On peut aussi combiner les méthodes: somme et filtre:
=SOMME.SI(C3:C18;”David";E3:E18)
Cette formule calcule uniquement la somme des valeurs de la plage C2:C5, dans laquelle les cellules correspondantes de la plage B2:B5 contiennent le mot « Jean ».
Base de données à plusieurs tables
Pour représenter les données, on peut utiliser un simple fichier texte. Pour séparer ces données, le plus courant est d’utiliser un séparateur par virgule (comma en anglais) : comma separated values (csv). Ce format convient bien pour des petites collections de données. Pour de plus grosses quantités, on utilisera des ensembles de tables, reliées entre elles par des règles et constituants des « bases de données » (database).
Pour une base de données à plusieurs tables, on utilise des clefs d’indexation permettant d’identifier rapidement chaque ensemble de données (comme un numéro d’article ou un numéro de client)
Exemple: voici un ensemble de données. Placer celles-ci comme nouvelles entrées dans les tableaux proposés.
Dupond Kevin, 21 ans, habite à Nice, voyage à Berlin le 06/12/24, son code client est le 756A
Pour son voyage à Berlin, la compagnie était Lufthansa, le vol était LF 231, à 7h01 et son numéro de siege le 31D.
Le passager voyageait seul et avait un bagage en soute de poids 14,6 kg, dont la reference bagage était 1234.
TP4 Formulaire d’enquête, conception du formulaire pdf et traitement Lien
Données à caractère personnel
culture numer
Une donnée à caractère personnel est une information sur une personne.
Parmi les données suivantes, certaines peuvent être classées comme relevant de:
l’identité numérique
identité administrative
indirectement nominative (qui donne l’identite de la personne, une fois effectué un recoupement d’informations)
Ce sont:
Le nom, le prenom, l’adresse
un pseudo, un mot de passe
une adresse IP
des lieux visités et géolocalisés
un panier d’achat
des clés de recherche sur internet
numero de carte bancaire
numero NIR (securité sociale)
données associées à son compte de reseau social (publications, like)
Données exposée par d’autres mais nous identifiant dans un reseau social
ordonance médicale, clichés radiographiques, …
L’enregistrement de la voix de clients ou salariés par un dispositif informatique
images de personnes physiques captées par un système de vidéosurveillance
les conversations (par le microphone)
le patrimoine d’un propriétaire
…
Même des données supposées anonymes peuvent nous identifier car il existe souvent une clé de correspondance qui peut nous identifier.
VIDEO Cash Investigation, le mythe de l'anonymisation
Mais alors, à qui servent ces données?
VIDEO Qui collecte nos données personnelles? - Le Tatoo (0-3min) puis Comment limiter la collecte de nos DCP (6min->fin)
Identité numérique
L’identité est construite à partir de données à caractère personnel.
L’exercice du droit d’une personne passe par la justification de l’identité administrative de la personne (nom, prenom, date de naissance, etc…).
Infographie du RGPD - site de la CNIL
Identité sur le net: Sur internet, la majorité des utilisateurs ne communiquent pas leur identité administrative. Ils donnent un pseudo, un mot de passe, un email. Le site associe souvent leur adresse IP à ces données. Ce qui constitue aussi une identité numérique.
Comment sont collectées nos données personnelles
(voir activité p 16 du livre SNT)
Les données nous concernant peuvent être cédées de manière:
volontaires, directement: à partir d’un formulaire à remplir
involontaires, indirectement: dans les metadonnées des photos de ma galerie, à partir du gps de mon telephone, de mon activité sur le net, de mes amis sur le net, de mon profil social sur les reseaux, …
Pour utiliser les services du net, on doit en contrepartie donner son accord pour partager certaines de nos données.
Lorsque l’on installe une application, un logiciel, un driver pour un objet connecté, on est souvent obligé d’accepter le contrat sur les Conditions Générales d’Utilisation (CGU).
De même, pour accéder à la plupart des sites d’information, on est obligé d’accepter en grande partie les cookies du site, qui vont enregistrer et partager certaines de nos données.
Les données nous concernant peuvent aussi être cédées de manière:
héritée: c’est lorsque ce sont d’autres personnes qui parlent de nous, ou publient des photos de nous, sur le net. (voir le chapitre sur les réseaux sociaux)
Pour résumer:
extrait d'une affiche sur le site de la CNIL
Traces numériques et marketing ciblé
Après 1978, c’est la valeur commerciale des données personnelles qui va commencer à aiguiser l’appetit d’opérateurs économiques: l’émergence d’une économie fondée sur la connaissance du client. Ce qui va intensifier la collecte de données à caractère personnel et amener à un marketing ciblé.
C’est la convergence technologique et la traçabilité qui permet d’intensifier cette collecte indirecte de nos données: des cartes à puces, cartes de fidélité client, videosurveillance, données de connexion aux réseaux numériques, moyens de paiement (cartes bancaires ou autre types de paiement numériques). On est passé d’une problématique de fichier à une problématique de traces numériques.
Comment peut-on limiter nos traces numériques?
Tous les cookies ne se valent pas : cookies « nécessaires » ≠ cookies « publicité / partage à des tiers ».
Cliquer sur « Tout accepter » maximise la collecte de vos DCP ; paramétrer réduit votre exposition.
Les CGU renseignent sur les données collectées et sur qui les reçoit : les consulter (même en diagonale) est un outil de choix.
Réduire sa collecte de DCP est possible par 2 leviers : le paramétrage des cookies ET le choix d’un service moins coûteux en données.
Traitement des données
Definition
il s’agit de toute opération effectuée de manière automatisée appliqué à des données à caractère personnel.
Par recoupement de plusieurs informations (publications, enregistrement par des dispositifs matériels, camera ou autre…), un algorithme peut déduire des informations sur ma personnalité, quelles sont mes préférences en terme de:
religion
sexualité
politique
Un ordinateur, ou bien une personne qui a accès à certaines données indirectes qui me concernent, peut retrouver mon identité.
extrait de l'Ep2 S04, recherche dans la base de données d'une boutique de location de films
Enjeux pour l’usager
Aujourd’hui, l’aspiration des individus, en termes de protection de leur vie privée est de pouvoir utiliser les services technologiques d’internet, de s’exposer personnellement (reseaux sociaux), tout en cédant une partie acceptable de leurs données personnelles. Cette part cédée doit rester raisonnable et être négociée par contrat avec les opérateurs économiques.
A quoi (à qui) sert cette collecte des données?
Imaginez un stade de football. Les panneaux publicitaires autour de la pelouse n’appartiennent pas au club qui joue le match : ils sont vendus par une agence intermédiaire à des annonceurs, qui paient pour être vus par les spectateurs présents et par ceux qui suivent le match à la télévision. Le club ne vend pas un morceau de terrain : il vend l’attention de son public.
Une page de site de presse fonctionne sur le même principe. L’espace publicitaire affiché n’appartient pas au site lui-même : il est vendu par une régie publicitaire à des annonceurs. Mais il existe une différence essentielle.
Au stade, tous les spectateurs voient le même panneau publicitaire au même moment. Sur le web, chaque lecteur peut voir une publicité différente, choisie spécifiquement pour lui à partir de son profil.
Une expérience similaire a été constatée pour l’Euro 2020: en Allemagne ou en France, les bandeaux publicitaires qui encadrent le terrain ne vont pas vous vendre la même chose.
numerama - Au foot tout le monde ne voit pas les memes pubs au bord du terrain
La société distributrice des panneaux d’affichage, Adi.tv s’est spécialisée dans le traitement des images, avant leur diffusion. Ces technologies numériques sont utilisées aujourd’hui pour la plupart des grands evenements sportifs, pour améliorer l’experience des telespectateurs, ou pour leur proposer des publicités plus ciblées.
Vox - How the NFL's magic yellow line works (start 1:55
Un triangle à quatre acteurs:
Quand un internaute consulte un site de presse gratuit, trois-quatre acteurs interviennent, même si un seul est visible.
L’éditeur: Le site de presse. Produit le contenu, mais a besoin de revenus pour exister sans faire payer le lecteur.
La régie publicitaire: Intermédiaire qui vend les espaces publicitaires du site à des annonceurs, souvent via une plateforme automatisée.
Les entreprises de l’adtech: plateformes technologiques. C’est l’ensemble des technologies, des logiciels et des algorithmes utilisés pour concevoir, cibler, diffuser et mesurer ces publicités de manière automatisée.
Les partenaires: Annonceurs, courtiers de données : ceux qui achètent l’accès à l’attention et aux données du lecteur.
l’éditeur ne vend pas seulement un espace sur sa page, il vend surtout l’accès à un lecteur profilé — et plus ce profil est précis, plus il se vend cher.
Le service est « gratuit » pour le lecteur, mais pas sans contrepartie : le financement du site repose en partie sur la vente de l’accès à son profil.
Le cookie n’est pas qu’un outil technique de confort (retenir un panier, une connexion) : il peut être la clé qui relie la navigation à ce marché publicitaire.
Paramétrer ses cookies plutôt que tout accepter limite concrètement le nombre de partenaires qui reçoivent des informations sur le lecteur — un des deux leviers vus dans ce cours pour réduire la collecte de DCP.
Le RGPD (Réglement Général pour la Protection de Données)
Définition
C’est un document qui donne un cadre légal à l’utilisation des données dans l’UE et contraint les organismes publics ou privés à certaines obligations.
Ce texte vise à définir des équilibres: protection des individus d’une part, utilisation des données à des fins commerciales ou pour des missions d’intérêt public, d’autre part.
Le RGPD n’interdit PAS l’utilisation commerciale des données.
Mais il fournit un cadre, auquel les entreprises privées, comme les administrations publiques doivent se conformer.
Obligations de conformité vis à vis du RGPD
Pour les entreprises et administrations, susceptible de TRAITER des données à caractère personnel:
devoir de tenir un registre des activités de traitement (finalités, délai de conservation et de suppression automatique, réalisation d’atude d’impact…)
obligation d’assurer une collecte lisible et transparente des données
protéger les données. Assure leur sécurité et leur confidentialité
définir un paramètre: Rester minimal dans la quantité de données et le type de données collectées
interdiction de collecter certaines catégories particulières de données (origines raciale ou ethnique, opinions politiques, convictions religieuses, appartenance syndicale)
interdiction de collecter le numero NIR (securité sociale) car celui-ci contient un certain nombre de caractéristiques qui aident au chainage des données
interdiction de collecter des données génétiques, biométriques, concerant la santé, la vie et l’orientation sexuelle.
Droit des personnes vis à vis du RGPD
Tout individu doit:
pouvoir être questionné pour demander son consentement préalable à la collecte et l’utilisation de ses données.
être informé sur la finalité du traitement qui sera effectué
dans le cas d’une collecte indirecte: être informé de la source de cette collecte, et droit de recours auprès de la CNIL
avoir droit d’accès, de rectification et de portabilité des données (c’est à dire, droit à obtenir ses données collectées dans un format structuré, lisible)
avoir droit d’effacement
avoir droit d’opposition au traitement des données à visée commerciale et de profilage
avoir des droits concernant les cookies, exploitant ses traces de navigation. Côté client, ces cookies sont stokées dans le navigateur web. L’individu doit donner son consentement sur leur utilisation, à partir d’une information claire et complète
avoir droit au deferencement: demander la suppression de liens vers des informations portant atteinte à la vie privée.
Remarques:
Il existe également un tracking côté serveur. Le client n’est alors pas en mesure d’effacer ses traces numériques, qui sont partagées le plus souvent avec des entreprises tierces (revente des données). Dans la chaine de partage des données, tout le monde est alors responsable du traitement qui sera effectué sur ces données.
De nombreux exemples montrent des manquements à ces règles sur la protection des données et leurs conséquences: L’affaire Facebook pendant l’élection américaine, qui a vu gagner le président Trump en est un tristement célèbre, même si cela ne concernait pas le territoire d’influence de la CNIL et de son équivalent européen. Au niveau fançais: les affaires Foncia, Acadomia…
La CNIL
Definition
Commission Nationale pour l’informatique et les libertés. La CNIL est la premiere autorité administrative instaurée en France (1978) à la faveur de l’adoption de la loi “informatique et libertés”.
Les actions de la CNIL
La CNIL exerce un pouvoir de contrôle et de sanctions pour la protection des données. Elle est indépendante et ne reçoit d’instruction d’aucune autorité publique.
Tout citoyen peut s’adresser à la CNIL pour la saisir d’une plainte.
La CNIL réalise des:
controles d’audit, qui sont programmés, sur des organismes privés comme publics.
contrôles de contentieux à partir de plaintes, de dénonciations anonyme ou de tout autre moyen qui lui aurait permi de prendre connaissance d’un manquement au RGPD.
La CNIL fait en sorte que l’usage qui est fait des données personnelles ne porte pas atteinte à la liberté des individus.
Sanctions prises
Lors d’un manquement avéré, la CNIL peut:
faire suspendre les flux de données adressés à un destinataire
prendre des sanctions pécunières
prendre des sanctions d’image: publication sur le site de la CNIL et dans le Journal Officiel. Les répercussions peuvent être importantes (risque réputationnel)
Le RGPD (Le règlement général sur la protection des données)
mai 2018
C’est un document qui donne un cadre légal à l’utilisation des données dans l’UE et contraint les organismes publics ou privés à certaines obligations. C’est un texte plus général que celui sur la loi informatique et libertés.
Le RGPD - affiche de la CNIL
Il s’agit d’un texte long (plusieurs centaines de pages), fruit de la concertation de 28 états membres de l’Europe. Ce texte est complexe à dechiffrer. Un des rôles de la CNIL est de produire des
documents et textes
Extraits:
La collecte de données doit servir l’objectif prévu. Ne collecter que celles nécessaires.
Les personnes doivent être clairement informés de l’utilisation qui sera faite de leurs données. Ce traitement n’est pas forcement informatisé. Mais tout traitement de données rentre dans le cadre du RGPD.
permettre aux personnes d’exercer leurs droits sur ces données.
Sécuriser ces données.
Violation de données et incidents de sécurité
Malgré toutes les mesures de sécurité mises en oeuvre, les violations et incidents peuvent survenir. En vertu du RGPD, les entreprises et administrations sont tenues d’informer l’autorité de contrôle (CNIL), ainsi que les individus concernés par le vol de données personnelles.
Ainsi, en 2024, les données de santé de 33 millions de français stockées pour le tiers payant (Aimerys) ont été hackées par des malfaiteurs. Elles ont pu être reversées dans le dark web, et contribuer à créer de fausses identités.
Mais, encore plus préoccupant, ce sont les données rendues publiques par les internautes, sur des sites internet, reseaux et applications sur leur smartphone qui sont les plus faciles à dérober.
Les reseaux sociaux et les clouds gratuits exploitent grandement ces données, qu’ils collectent massivement.
paramétrer son smartphone pour éviter la fuite de ses données
Il est essentiel de connaitre les risques et d’adopter une attitude modérée lorsque l’on utilise ces outils.
Vie privée et traces numériques, persistance sur le net
Comme vos données sont personnelles, elles vous concernent et vous devez en avoir la maitrise.
Conserver des secrets sur sa vie privée est relativement difficile lorsque l’on s’expose sur internet.
Le format numérique des données va faciliter leur échange, leur multiplication, … et leur persistance sur le web.
Il est souhaitable d’avoir un compte privé sur les réseaux sociaux, et de diffuser le moins d’informations possibles. Mais les algorithmes utilisés par les réseaux sociaux vont chercher à déduire des informations à partir d’indices:
Votre activité sur les reseaux sociaux
Les personnes que vous suivez, les pages que vous likez, … sont autant d’informations pour établir votre profil par recoupement d’information.
Données de Géolocalisation
Il s’agit d’un exemple de données personnelles indirectement nominatives. Celles-ci contribuent aussi à fournir une information sur la personne (habitude, travail, consultation de médecin)…
Données personnelles, Google vous suit à la trace - FranceTV info
Il existe cependant quelques gestes et attitudes qui peuvent limiter nos traces numériques, ainsi que la confidentialité des données que l’on échange.
Questions-reponses
une entreprise peut-elle être tenue responsable du vol des données de ses clients?
Q/R issu du site europe-consommateurs.eu
Lorsque vous acceptez la collecte, transfert, sauvegarde, utilisation de vos données par un professionnel:
Doit-on vous informer de l’utilisation qui est faite de vos données ?
Oui. Vous avez le droit de savoir si vos données sont collectées, transférées, sauvegardées, modifiées…
Vous devez également être informé, entre autres, :
de l’identité du responsable de la collecte de vos données.
des finalités de cette collecte.
des destinataires de vos données.
de la durée de conservation de vos données.
de votre droit d’introduire une réclamation auprès d’une autorité de contrôle.
Les entreprises américaines comme Uber ou Amazon, …, doivent-elles se conformer au RGPD?
Oui car le RGPD est un texte de loi qui protège les citoyens européens (pour leurs données personnelles), même ci ceux-ci utilisent des services proposés par des entreprises hors UE, dès lors qu’elles ciblent des usagers européens.
Comment protéger mes données lors d’un achat en ligne ?
Assurez-vous que vous payez votre commande sur un site utilisant une connexion sécurisée. L’adresse du site doit commencer par « https:// » et un cadenas fermé doit apparaitre.
Pour éviter le piratage de vos données bancaires, vous pouvez privilégier l’utilisation d’une carte bancaire à usage unique.
Un site marchand européen a-t-il le droit de garder mes coordonnées bancaires pour faciliter mes futurs achats ?
Oui mais seulement si vous y avez consenti expressément en cochant une case. Accepter simplement les conditions générales de vente ou passer par une case pré-cochée ne suffit pas.
Vous pouvez à tout moment contacter le professionnel afin de demander la suppression de vos données bancaires.
Comment protéger mes données sur les réseaux sociaux ?
Pour protéger votre vie privée, paramétrez l’accès à vos photos et à votre profil. Vérifiez régulièrement le paramétrage de confidentialité de votre compte.
Evitez de répondre aux questions de géolocalisation si cela n’est pas indispensable. Surtout, ne répondez pas aux messages adressés par des individus que vous ne connaissez pas.
Laissez également le strict minimum concernant vos coordonnées et évitez d’y détailler votre vie privée, pour rester à l’abri de personnes malintentionnées.
Un réseau social basé en Europe refuse de me donner accès à mes données personnelles. Vers qui dois-je me retourner ?
Si vous résidez en France, vous pouvez adresser une plainte à la Commission Nationale Informatique et Libertés (CNIL) en cas de violation de vos droits. La CNIL se chargera d’en informer l’autorité chef de file. Il s’agit de l’autorité nationale de protection des données personnelles du pays dans lequel le professionnel/le réseau social est établi.
Je n’utilise plus mon compte sur un réseau social, mes données sont-elles supprimées ?
Non pas automatiquement. Ce n’est pas parce que vous ne vous êtes pas connecté à votre compte sur un réseau social depuis plusieurs années qu’il a supprimé vos données personnelles et ne les exploite plus. Renseignez-vous bien quant au devenir du compte que vous n’utilisez plus sur un réseau social.
Les autorités de protection des données personnelles dans l’Union européenne recommandent aux différents réseaux sociaux de supprimer les comptes restés inactifs pendant une certaine période mais ces recommandations ne sont pas toujours respectées.
Veillez donc à supprimer votre compte.
Mon enfant de 14 ans peut-il s’inscrire seul et confier ses données à un réseau social ou un jeu en ligne ?
Pas sans votre consentement car la majorité numérique en France est à 15 ans. En Europe, le RGPD a laissé le soin à chaque pays de fixer sa « majorité numérique » qui doit être entre 13 et 16 ans.
Peut-on m’imposer de recevoir des publicités pour valider ma participation à un jeu concours ?
Non. Aucune jeu concours ne peut conditionner votre participation au fait que vous acceptiez de recevoir une prospection commerciale, ou de communiquer vos coordonnées à des partenaires de l’organisateur du jeu. Vous devez pouvoir participer au jeu concours de manière libre. De la même manière, l’organisateur du jeu ne peut prévoir de vous accorder des chances supplémentaires au tirage au sort du jeu concours à condition que vous acceptiez de recevoir une prospection commerciale.
Les informations recueillies ne peuvent être utilisées que dans le cadre du jeu et de la remise du lot en cas de gain, sauf si vous avez consenti à recevoir de la prospection.
Le site Internet du restaurant-livreur de pizza, sur lequel vous avez renseigné des données personnelles est victime de hacking. Est-ce grave ? Doit-il informer ses clients ? Est-il responsable de l’usage qui sera fait de ces données ?
Vous pouvez contactez la CNIL et cybermalveillance.gouv.fr, même si en principe l’entreprise doit effectuer la démarche. Demandez à l’entreprise des informations détaillées sur l’incident : date et contexte exact, origine de l’attaque, quelles données le hacker a-t-il exactement dérobées (identité, coordonnées, informations financières, numéro de sécurité sociale…) ? Quels documents a-t-il récupérés (copie de la carte d’identité, des fiches de salaires, justificatifs bancaires….) ? Est-ce que l’entreprise victime a bien fait une déclaration à la CNIL ? Réagissez à temps, afin d’anticiper une potentielle usurpation d’identité via les données volées !
Compléments et activités
Se proteger de la collecte des données (videos/TD): Lien
Un pieton a été renversé par une voiture dans la nuit du 02 septembre 2022.
Vous enquêtez sur cet accident. Vous diposez d’une base de données comprenant:
des témoignages
un fichier d’immatriculation des vehicules
un fichier des personnes enregistrées au cours d’autres enquêtes réalisées par la police: les données de personnes fichées, ou bien temoins, soupçonnées, ou déjà condamnées.
un fichier avec références pour les données biométriques.
Vous recherchez un procès verbal qui contient le mot voiture, ou accident, ou encore pieton.
Le fichier peut être long à lire, alors utilisez les fonctions de recherche du logiciel:
Cliquer sur le repère de la colonne
Dans les fonctions du logiciel, choisir Rechercher et remplacer > Rechercher (on peut s’aider du menu Aide). Placer alors votre mot-clé voiture dans les paramètres de recherche
Sélectionner une à une toute les lignes qui contiennent voiture en appuyant sur Suivant
Placer des informations dans une feuille Excel
Au cours de l’enquête, vous aurez besoin de mémoriser des informations, et de les placer dans un tableau. Utiliser une nouvelle page du fichier en appuyant sur + en bas de page.
Puis remplir vos informations dans la feuille:
Travail (à rendre sur feuille)
A. Questions sur l’enquête
Quels renseignements relevez-vous dans la page témoignages du fichier?
Comment utilisez-vous les renseignements donnés par les différentes pages du fichier pour identifier le-s suspect-s? Préciser le lien existant entre chaque page du fichier?
Quels sont les suspects identifiés? (remplir un tableau sur Excel et le montrer au professeur).
Quel est alors le PRINCIPAL suspect? Pourquoi?
L’enquête à partir de ces fichiers va-t-elle, à coup sûr, permettre de désigner le coupable? Expliquez
B. Prolongement: questions sur la protection des données personnelles
A partir des liens proposées ci-dessous, ou bien d’autres issus d’une recherche personnelle, repondez de manière argumentée à au moins une des questions suivantes:
Quelles personnes sont renseignées dans le fichier de la police? Des criminels, des personnes ayant eu affaire avec la justice, les victimes, ou bien tout citoyen français?
La CNIL va s’opposer à l’existance d’un fichier du type de celui appelé proprietaire dans le classeur. Pourquoi?
L’activité est inspiré d’un document de la page SNT du site monlyceenumerique.fr
TP Pommes
Format des données
Les données structurées sont stockées dans des fichiers contenant des caractères. Ces fichiers peuvent être utilisés par plusieurs logiciels (interopérabilité), à condition que les données y soient mises dans un le bon format.
Nous allons voir ici l’un de ces formats: Le csv, ou comma separated values.
Voici un exemple de données en format csv. Il s’agit d’informations sur les vendeurs de fruits d’une compagnie, sur le territoire français.
Copiez ces données et collez les dans un fichier à l’aide de Notepad (du menu Programmes > accessoires de l’ordinateur).
Sauvegardez le fichier dans votre dossierdocuments en le nommant: fruits.txt, ou bien "fruits.csv"
Question a: A partir de vos connaissances, ou bien après une petite recherche sur le net quelle différence y-a-t-il entre un fichier à l’extension .txt et un fichier .csv? Les données y-sont-elles mises dans un format special (structuré) pour l’un de ces 2 types de fichiers?
Présenter les données à l’aide d’un tableur
Démarrer le logiciel Excel (un tableur de la suite bureautique microsoft).
Une fois le logiciel Excel démarré, ouvrir le fichier fruits.txt
A l’ouverture, il vous sera demandé de préciser le séparateur des données (, ou bien ;), puis l’encodage et les caractères.
Selon la version du logiciel Excel, la boite de dialogue peut différer:
le format n'a pas été correctement renseigné
Le paramètre semicolon (point virgule) précise le caractère séparateur.
le format a été correctement renseigné
Dans une version plus recente, la boite de dialogue peut ressembler à celle-ci:
à gauche, les caractères accentués ne sont pas gérés. à droite, en utf-8, les caractères accentués sont pris en charge.
Pour l’encodage des données, choisir utf-8. Cela permetra d’afficher aussi les caractères accentués.
Le logiciel Excel sert à PRESENTER les données. C’est à dire à reconstruire le tableau. Le visuel peut être important pour lire les informations contenues.
Vous devriez obtenir un tableau (lignes, colonnes, cellules, texte, couleurs) comme celui présenté ci-dessous:
exemple de présentation structurée des données en tableau
Question b: Comment le logiciel a-t-il analysé le contenu du fichier pour obtenir cet affichage, en lignes et en colonnes?
Maintenant que la présentation est satisfaisante:
ajoutez l’information suivante, en renseigant certaines valeurs dans le tableau:
le commercial Sébastien a vendu 9814 Pommes dans la région Sud
Question c: Quelles sont les réferences (coordonnées) des cases dans laquelle vous avez renseigné Sébastien, Pommes, région Sud, 9814? Justifier.
Rechercher et Filtrer
Rechercher
Souvent, les tables contiennent de très nombreuses lignes, et ne peuvent pas toutes être présentées à l’écran. Il faut alors utiliser la fonction de recherche (bouton LOUPE à droite).
Utiliser le bouton pour rechercher le nom Alain. Cliquer sur Suivant.
Question d: Quelles sont les réferences des cases qui sont sélectionnés lorsque l’on clique plusieurs fois sur Suivant?
Filtrer par critère simple
Le fichier, lorsqu’il est importé depuis le bandeau Données, s’ouvre dans un classeur avec filtres.
à gauche: ouverture du classeur AVEC filtres. à droite, ouverture SANS filtres
Si la feuille de calcul ne présente pas de filtres en tête de colonnes:
Commencer par selectionner toutes les colonnes A, B, C, D, E dans laquelles se trouvent les données du tableau.
Dans le bandeau Données, choisir Filtrer (entonoir).
Il apparait alors des listes de choix au dessus des descripteurs du tableau. Pour filtrer selon l’un des descripteurs, cliquer sur l’une de ces listes de choix:
Sur le filtre appliqué à la première colonne (étiquette: Région), choisir Est.
menu permettant la sélection par Région
Filtrer selon un 2e critère
Sur le filtre appliqué à la troisième colonne (étiquette: Produits), choisir Pommes.
Vous devriez obtenir un tableau ressemblant à celui-ci, mais avec plus de lignes:
exemple de tableau filtré par Région ET par Produit (n'affiche que la 1ere ligne)
Question e: Combien de lignes sont affichées dans ce tableau filtré? Qu’ont-elles en commun?
Les fonctions de calcul
Somme de toutes les valeurs de la colonne Unités
Pour revenir au tableau initial, rappuyer sur Filtre dans le bandeau d’Excel.
Cela retire tous les filtres.
Fonction somme
Vous allez maintenant programmer une fonction de calcul sur le tableau: La fonction SOMME.
cliquer dans la cellule juste sous la dernière valeur de la colonne Unités.
Ecrire debut de la formule: = SOMME(
puis faire une sélection étendue de toutes les valeurs de la colonne.
Valider avec la touche Entrer
Question f: Quel est le resultat du calcul? Si le resultat est égal à zero, veuillez modifier le format comme expliqué en bas de page (Compléments), puis recommencer.
Question g: Cliquer dans la case. Recopier la formule du calcul généré par le logiciel.
Somme conditionnelle: SOMME.SI
La fonction SOMME.SI permet de sélectionner certaines cellules d’une selection étendue.
On va s’aider du concepteur de formule: Cliquer dans la cellule dans laquelle vous souhaitez rentrer la formule, sous le tableau, puis:
écrire = SOMME.SI(
somme conditionnelle
cliquer sur le bouton fx de la barre de saisie.
Aidez vous des champs suivants pour remplir les plages pour cette formule:
Plage: faire une selection étendue des valeurs de la colonne Produits
Critères: écrire “Pommes”, ou bien cliquer sur le mot “Pommes” dans l’une des cellules du tableau (la C24 dans cet exemple.
Somme_plage: selectionner toutes les valeurs numériques de la colonne Unités:
concepteur de formule pour SOMME.SI
On a alors le nombre de Pommes vendues dans toute la France.
Question h: Quel est le résultat? Recopier aussi la formule qui a été générée.
Conclusion
Un logiciel tableur (Excel, Calc, Number) permet de présenter les données à l’utilisateur en tableau, mais apporte aussi des fonctions de traitement. Ce sont les mêmes fonctions que l’on peut programmer avec un langage de traitement sur une Base de Données (SQL).
Question i: Quelles sont les fonctions de traitement que vous avez utilisées lors de ce TP? Donner leur nom.
Quel est le meilleur commercial?
Dans cette entreprise, les pretendants au titre de meilleur commercial sont Maurice, Jérome et Sébastien.
Question j: Utilisez la somme conditionnelle pour calculer le nombre de fruits total vendu par chacun des ces 3 commerciaux. Placez les résultats dans un nouveau tableau, sur la même page. Recopier ce tableau sur votre feuille. Décidez enfin: Qui remporte le titre de meilleur commercial?
Compléments
Format numérique
Lors de l’import des données, le format des cellules est parfois incompatible avec les fonctions de calcul.
Il faut alors définir une plage de valeurs numériques.
Sélectionner toutes les valeurs numériques du tableau.
Dans le bandeau Données, choisir: Convertir. Et faire suivant, plusieurs fois, sans changer les options proposées. Les cellules sont maintenant en format NOMBRE.
reseaux sociaux
Projet de fin de séquence:
créer une campagne de sensibilisation (affiche + post type Instagram/TikTok fictif) sur un enjeu réel : cyberharcèlement, désinformation, addiction au scroll, ou effet de bulle de filtre. Justifier le choix (ciblage, algorithme de recommandation, mécanismes d'engagement) en s'appuyant sur ce qui a été vu en cours.
Variante plus technique : concevoir le cahier des charges d'un "réseau social idéal pour lycéens" en explicitant les paramètres de confidentialité et leurs compromis.
identité numérique, modélisation des liens d’amitié, aspects economiques et sociaux
Sous-sections de reseaux sociaux
reseaux sociaux
Black Mirror - Chute Libre S03EP01 commenté
“La Mythocritique transhumanisme dans NoseDive (S3E1 - Black Mirror)”. Intervention proposée dans le cadre du 11ème Colloque International “Beyond Humanism”, à l’Université Catholique de Lille, le 12 juillet 2019.
Definition d’un reseau social
Ca sert à…
Les reseaux sociaux sont des applications qui servent à créer des « communautés ». Il permettent aux usagers d’utiliser un compte public ou privé.
Il permet de communiquer de manière instantanée, et se substituent peu à peu aux autres formes de communications par voie électronique (mails…).
L’emergence des reseaux sociaux vient de l’apparition des premiers smartphones, qui ont permis de nouveaux services grâce au partage de photo, video, medias…
Les applications de type RS ont des fonctionnalités étendues qui sont en convergence (utilisation de hashtag, post de texte, img, video, reactions de type LIKE, interopérabilité…)
Les réseaux sociaux combinent trois fonctions fondamentales :
support de l’identité numérique ;
moyen de sociabilité sur la base de critères d’affinité ;
média réticulaire de communication interpersonnelle et/ou intergroupe.
moyen de se distraire
Au démarrage: il faut créer un compte, le paramétrer. Il est conseillé de limiter la portée des données personnelles publiques lors de ce paramétrage. Par exemple, bloquer la lecture de votre liste d’amis, ne pas rendre votre mail et numero de telephone accessible à tous.
L’activité sur le réseau social va aussi construire une identité numérique. Il est recommandé d’avoir une certaine hygienne sociale avec son activité sur les reseaux.
identité numérique
L’identité numérique est de son côté le lien entre une personne et ses informations virtuelles, pouvant être trouvées par le biais d’une simple recherche sur Internet. Cette identité est multiple: la personnalité que vous construisez est différente selon le reseau social utilisé et la manière avec laquelle vous l’utilisez.
Toute activité sur le Web implique la création de traces. Certaines sont volontaires, d’autres involontaires. Elles sont collectées, partagées entre applications et stockées dans des bases de données. Leur addition construit l’identité numérique de chacun.
Une conséquence de l’usage d’un ou plusieurs RS est la constitution d’une veritable identité numérique pour la personne, puisque chaque reaction/publication, surf, se fait avec sa propre identité.
e-reputation
La e-reputation est due à l’identité numérique que l’on se construit, mais aussi par ce qu’en disent les autres.
La e-réputation a tendance à définir, aux yeux des autres, ce que vous êtes, selon la manière dont on parlera de vous, positivement ou négativement. Cette notoriété Internet peut pencher d’un côté comme de l’autre, en tout cas elle sera très représentative de la manière dont on vous percevra, qui que vous soyez.
Les sites de vente en ligne permettent aux usagers d’être egalement vendeurs. La reputation du vendeur (et de l’acheteur) se construit au fil de ses transactions, grâce aux notes obtenues.
Viralité: Avec les reseaux sociaux, la propagation d’une information, surtout si elle est sensationnelle, se fait très facilement, à une très grande echelle. Cette propagation explosive vient de la manière avec laquelle les usagers sont en relation. C’est ce mécanisme qui agrave les problèmes de cyberharcelement.
Pour comprendre comment se propagent les informations, on a cherché un moyen de représenter visuellement l’organisation du réseau social. D’où l’utilisation des graphes.
Dans un réseau du genre de « Facebook », où l’amitié est une relation symétrique, on va donc représenter chaque personne par une bulle (les sommets du graphe) et chaque relation par un lien entre deux bulles (les arêtes du graphes).
Utiliser une représentation visuelle: le graphe
Graphe non orienté
A faire soi-même :
Construire le graphe de relations amicales (type Facebook) du petit groupe suivant :
Ashley est amie avec Benoit, Dido et Ela
Benoit est ami avec tout le monde
Cédric est ami avec Benoit et Ela
Dido est ami avec Ashley et Benoit
Ela est amie avec Ashley, Benoit et Cédric
Déterminer quelle est la personne la plus influente dans ce réseau
Quel chemin va emprunter une publication, systématique re-publiée, pour parvenir de Denis à Camel?
Corrections : 3 visualisations de la même situation
Seule la 3e visualisation montre clairement que Benoit est l’élément central de ce graphe. On verra plus loin que la seule représentation visuelle ne permet pas toujours de faire des mesures sur le graphe. Il faudra la plupart du temps utiliser un algorithme.
Graphe orienté
Dans un réseau social comme « X, ex-Twitter », il s’agit de s’abonner à quelqu’un pour suivre ses publications. La relation est à sens unique, si vous suivez quelqu’un cette personne ne vous suit pas forcement.
La flèche traduit alors une relation. Cela peut être, au choix:
suit …
est suivi par…
De tels graphes permettent ainsi aux sites de réseaux sociaux de vous proposer de nouveaux contacts, lieux ou autres en fonction de vos envies et de vos connaissances.
Exemple:
D’après le diagramme précédent, quelle visite pourrait-on conseiller à Bob ?
Supposons que Bill et Alice visitent la tour Eiffel en même temps, et que leurs données de géolocalisation sont partagées avec l’application de reseau social. Que pourrait faire l’appli?
Mesures sur un graphe
Pour le graphe non orienté suivant, comportant une centaine de sommets, on établit 2 représentations:
a gauche: graphe non organisé, a droite: organisé
Le graphe de droite est organisé en plaçant tous les sommets sur une couronne.
Le graphe de gauche montre que certains sommets sont plus connectés que d’autres. A droite, ces mêmes sommets sont répartis régulièrement sur la couronne.
Repérer ces sommets particuliers sur chacun des 2 graphes
Quel est la signification de ces connexions plus nombreuses pour certains sommets?
On donne 2 représentations d’un nouveau reseau:
Que fait apparaître cette organisation des sommets?
Quelle peut être la conséquence de ces regroupements sur les réseaux sociaux, et dans un contexte élargi : à la vie offline?
Definitions
La distance entre deux sommets d’un graphe est le nombre minimum d’arêtes pour aller du sommet à un autre. La distance entre a et f est 2.
L’écartement d’un sommet est la distance maximale existant entre ce sommet et les autres sommets du graphe. Pour le sommet a, la plus grande distance avec un autre sommet est 2. L’écartement est donc de 2.
Le centre d’un graphe est le sommet d’écartement minimal (le centre n’est pas nécessairement unique). Ci-contre, tous les sommets ont un écartement de 2, sauf d qui a un écartement de 1. Le centre est donc d.
Le rayon d’un graphe G est l’écartement d’un centre du graphe. Ici d est le centre et d a un écartement de 1. Donc le rayon est de 1
Le diamètre d’un graphe est la distance maximale entre deux sommets du graphe. Ici le diamètre est de 2.
Le degré d’un sommet est le nombre de sommets qui lui sont connectés. Il s’agit du nombre d’amis.
Le rayon et les centres du graphe vont permettre d’identifier les presonnes les plus influentes du reseau.
A vous de jouer. Pour simplifier, imaginons un réseau social ne possédant que 7 abonnés :
Déterminez-le (ou les) centre(s) du graphe ci-contre.
En déduire le rayon du graphe.
Déterminer le diamètre du graphe.
Représenter les relations d’amitié dans un tableau
L
M
N
O
P
Q
R
M
N
O
P
Q
R
Ce tableau, permet-il de repondre plus facilement aux 3 premieres questions?
Experience de Milgram
Milgram envoie soixante lettres à des recrues de la ville d’Omaha dans le Nebraska. Il leur demande de faire suivre cette lettre à un agent de change, vivant à une adresse fournie, dans la ville de Sharon dans le Massachusetts. Les participants pouvaient seulement passer les lettres, de main à main, à des connaissances personnelles qu’ils pensaient être capables d’atteindre l’objectif.
Remarque: Une des difficultés dans la conduite de ces études tient à la supposition que les gens dans la chaîne sont compétents pour découvrir le lien entre les deux personnes servant de terminaux. Ceci est plus evident avec des communautés, dans lequel le chemin entre usagers va exister et être relativement court. Mais il n’est pas certain que le monde lui-même soit un petit monde
Le cas des influenceurs
Voir le paragraphe plus haut les mesures sur un graphe, et la recherche de centres.
Paradoxe des communautés
Quels éléments permettent aux algorithmes des réseaux sociaux de produire des clusters?
Véracité contre viralité, désinformation
Petits mondes
Sur le document suivant, on voit que les groupes à centre d’intérêt spécifique, ou communautaires peuvent avoir des liens fragiles entre-eux.
En 2015 à Bombey, en Inde, le gouvernement a interdit la consommation de viande. La situation a fait polemique dans le pays et notamment sur Twitter, où le hashtag #BeefBara été largement repris.
Sur le document suivant, on a colorié en vert et en rouge les tweets pour et contre l’interdiction de la consommation de viande. On constate un lien étroit entre les opinions et l’appartenance à une communauté. extrait du livre Delagrave SNT p135.
Les reseaux sociaux conduisent fréquemment à rester dans un “petit monde” où l’on est en relation avant tout avec des personnes qui nous ressemblent et pensent comme nous, au risque d’un certain repli sur soi.
Aspects économiques et controverses
Victimes des algorithmes.
L’usager d’un reseau social est soumis, voire manipulé par les algorithmes de celui-ci.
Mais quels sont ces algorithmes au final? Et comment parviennent-ils à nous fournir un contenu personnalisé?…
Les reseaux sociaux parlent pour nous
La collecte de données personnelles est le ciment du modèle économique des réseaux sociaux. Au regard de ce que l’on vient d’apprendre, cela fonctionne comme un cercle vicieux :
Plus l’on interagit sur les plateformes numériques, plus elles enregistrent nos données personnelles.
Plus elles enregistrent nos données personnelles, plus elles personnalisent nos flux d’informations, en usant d’objets techniques liés à l’économie de l’attention.
Plus nos flux d’informations sont personnalisés, confortables et rassurants, au détriment de ce qui se passe en dehors de ces chambres d’écho (bulle d’informations), plus nous passons de temps sur les plateformes numériques.
… et plus nous interagissons et produisons de données personnelles. Algorithmables, mémorisables, monétisables, profilables par les plateformes numériques.
Et cela déborde de la sphère économique pour empiéter dans la sphère psychologique…
Une journaliste parisienne inscrite sur un fameux site de rencontre a décidé de réclamer ses données personnelles auprès du site.
Pour 1’équivalent d’une fréquentation de 4 années, el1e a reçu
pas moins de 800 pages résumant les différents aspects de sa vie privée : ses « likes » sur Facebook, ses photos postées sur Instagram, ses diplômes universitaires, mais aussi ies dates, lieux et contenus de ses conversations… Que pourrait-il se passer dans le cas oit
ces informations seraient divulguées ou revendues à une autre entreprise ?
Témoignage : elle réclame ses données et reçoit". " 800 pages !
D’après Libération
Addiction
Les reseaux sociaux peuvent repondre à un besoin de reconnaissance. Cela peut entrainer un comportement addictif dans leur usage, en multipliant les parutions ou autres activités (partage, like).
C’est à partir de ce constat que Beomseok Yang, réalisateur sud-coréen, a décidé de produire un court-métrage montrant l’addiction aux réseaux sociaux. Notamment chez les jeunes.
La vidéo, intitulée “Social Network”, nous permet de suivre la journée d’un jeune homme en mettant en avant toutes les interactions sociales qu’il a au cours de cette journée.
Beomseok Yang: SOCIAL NETWORK
Are You Living an Insta Lie? Social Media Vs. Reality
Les reseaux sociaux mettent en place des fonctionnalités addictives pour vous faire passer plus de temps sur leur plateforme. Il est prouvé que passer plus de 30 min par jour sur ces reseaux sociaux augmente l’anxiété et le sentiment de solitude.
De plus, l’utilisation d’appli tierces (jeux, quizz) constitue une menace pour nos données confidentielles, et renforcent le marketing ciblé dont on oeut faire l’objet.
Pour comprendre ce qui apparaît sur notre Newsfeed au moment où l’on se connecte à Facebook, on peut comparer l’algorithme du réseau social aux mécanismes qui nous permettent de choisir un menu au restaurant.
NOTA : ressource élaborée d’après l’article publié sur le site Le blog du modérateur, par Thomas Coëffé, le 27 octobre 2017.
Cyberviolence
Def:
la cyberviolence, c’est l’acte agressif et intentionnel perpétré par un individu ou un groupe d’individus au moyen de formes électroniques de communication.
le cyberharcelement consiste en des agissements malveillants répétés, dans un cadre public ou restreint, qui peuvent prendre différentes formes : intimidations, insultes, menaces, rumeurs, publication de photos ou vidéos compromettantes, etc.
Avec Ies spécificités du numérique, on ajoute un impact plus conséquent aux violences. En effet, les contenus offensants peuvent se répandre très rapidement grâce aux reseaux qui accelerent et grandissent l’échelle des échanges. D’autre part, le caractere anonyme des echanges favorise le sentiment d’impunité. Une certaine distance s’installe et diminue la capacité d’empathie ou la conscience de ses actes.
Dans certains cas, il rend aussi difficile l’identification de l’auteur. Enfin, les cyberviolences n’ont pas de limite temporelle: elles laissent toujours une trace. Une fois diffusée sur la toile, on ne peux plus maitriser son cheminement. d’après un document de SNT Nathan p76
Droit pénal
Le fait de harceler une personne par des propos ou comportements répétés avantpour objet ou pour effet une dégradation de ses conditions de vie se traduisant par une altération de sa santé physique ou mentale est puni d’un an d’emprisonnement lorsque ces faits ont causé une incapacité totale de travai[ inférieure ou égale à huit jours. Ou et de 15 000 € d’amende si cela n’a entraîné aucune incapacité de travait. Article 222-33-2-2 du code penal
Typologie des Cyberviolences
Droit à l’oubli
grâce à l’arrêt de la Cour de justice de l’Union européeenne du 13 mai 2014, il est possible de réclamer le “droit à l’oubli”. Pour l’appliquer, il faut demander au site d’origine de supprimer les information outrageuese et au moteur de recherche de ne plus les référencer.
Travaux pratiques dans la partie Compétences numeriques > publier du site
le Web et les moteurs de recherche
Le world wide web, ou toile en français, est un service construit sur l’infrastructure du reseau internet pour mettre à la disposition des utilisateurs des documents repartis au niveau mondial.
Lors de sa navigation, l’usager d’internet va suivre des liens qui connectent les pages entre-elles (ce que l’on appelle surfer sur le Web).
Historique du 3w
Le “World Wide Web”, plus communément appelé “Web” a été développé au CERN (Conseil Européen pour la Recherche Nucléaire) par le Britannique Sir Timothy John Berners-Lee et le Belge Robert Cailliau au début des années 90. À cette époque les principaux centres de recherche mondiaux étaient déjà connectés les uns aux autres, mais pour faciliter les échanges d’information Tim Berners-Lee met au point le système hypertexte. Le système hypertexte permet, à partir d’un document, de consulter d’autres documents en cliquant sur des mots clés. Ces mots “cliquables” sont appelés hyperliens et sont souvent soulignés et en bleu. Ces hyperliens sont plutôt connus aujourd’hui sous le simple terme de “liens”.
Normalisation de la présentation de l’information (w3c)
Le bon fonctionnement du www nécessite le respect de normes et de formats de fichiers et de protocoles entre serveurs et clients.
Le World Wide Web Consortium, abrégé par le sigle W3C, est un organisme de standardisation à but non lucratif, fondé en octobre 1994 chargé de promouvoir la compatibilité des technologies du World Wide Web telles que HTML, CSS, JS, …
W3C: un organisme qui définit les standarts du web
Le web fonctionne avec : le protocole HTTP (HyperText Transfert Protocol), les URL (Uniform Resource Locator) et le langage de description HTML (HyperText Markup Language).
La lecture et l’usage des hyperliens d’une page html nécessite d’utiliser un navigateur.
On peut entrer dans une page directement en saisissant son URL.
On peut alors se demander: Comment est tissée la toile du web? C’est à dire, comment sont reliées ces pages les unes aux autres…
Tout d’abord, il y a les liens hypertext. Ces liens permettent la navigation de page en page, et c’est comme cela que l’on peut utiliser le Web.
Ensuite, il y a l’entrée par un moteur de recherche.
Trouver une page: moteurs de recherche
Principe
Avant l’usage généralisé des moteurs de recherche, les sites étaient référencés par dans des annuaires web: répertoire web, annuaire Internet ou répertoire Internet est un site web proposant une liste classée de sites Web.
Le classement se fait typiquement dans une arborescence de catégories, censée couvrir tout ou partie des centres d’intérêt des visiteurs.
Aujourd’hui, ils ont perdu de l’interêt face à la facilité d’utilisation des moteurs de recherche, et ne sont plus utilisés que dans des cas particuliers voir article
dernière page de l'annuaire Yahoo avant sa fermeture en 2014
Un moteur de recherche: Logiciel qui dispose d’une indexation des pages internet. Son fonctionnement repose sur plusieurs étapes, qui sont executées en continu:
La collecte automatique d’informations, par des robots d’exploration (Crawlers), qui parcourent le reseau hypertexte du web.
Le référencement: un traitement qui consiste à analyser des pages pour y detecter des mots clés utilisés fréquemment par les internautes. L’indexation, est la manière dont le moteur de recherche organise ces informations. Il va créer une table de mise en correspondance mot-clé <=> URL de la page.
L’internaute va utiliser l’interface du moteur de recherche pour faire une recherche par mots-clés:
Traitement de la requête: Les mots clés sont comparés avec ceux référencés et le moteur de recherche construit une liste ordonnée, un classement établi grâce à un calcul selon un algorithme. C’est un classement par degré de pertinence.
Le moteur de recherche va retourner une liste ordonnée de liens en rapport avec les mots clés proposés par l’internaute.
L’utilisateur va alors cliquer sur le lien de son choix parmi les propositions du moteur de recherche. Et se retrouver sur la page proposée, sans avoir à connaitre et mémoriser son URL.
fonctionnement d'un moteur de recherche
Mooc SNT: internet et le web: 3'00 et plus (moteurs de recherche)
video: Mooc SNT internet et le Web + moteur recherche
a) Comment fait un moteur de recherche pour trouver des milliards de pages du Web ?
b) Comment fait le moteur de recherche pour faire un classement entre ces pages ? Qu’est-ce que le SEO (Search engine optimisation)
c) Quand vous avez cinq à six mille ordinateurs qui travaillent pour vous, il est certain
que plusieurs tomberont en panne chaque jour. Comment un moteur de recherche fait-il pour ne jamais s’arrêter ?
d) Pour fabriquer un index, il faut lire toutes les pages qu’il index sur le Web. Le moteur
de recherche n’a pas fini de les lire que certaines pages ont déjà changé et qu’il lui faudrait les relire. Et découvrir de nouvelles pages… Comment se tenir au courant des « nouveautés » du Web ?
e) On fait des fautes d’orthographe. Comment un moteur de recherche peut-il répondre aux questions quand les textes et les questions contiennent des fautes ?
f) Moteur de recherche et IA générative : Les moteurs de recherche évoluent et proposent maintenant de nouvelles expériences. Quelle est la différence entre un moteur de recherche, comme Google, et une application de génération de texte à base d’IA comme Chat GPT ?
Les surprises à venir des moteurs de recherche - FRANCE 24
Les firmes OpenAI, Google ou encore Perplexity vont modifier notre manière de rechercher sur Internet.
ChatGPT, conçu par le groupe OpenAI, est un Logiciel de Traitement automatique du langage naturel. Il repose sur un modèle d’apprentissage automatique et une architecture de réseau neuronal.
OpenAI a dû former le modèle à travers une quantité importante de données pour que le système puisse interagir de manière naturelle avec un interlocuteur humain. (lecture de livres, de blogs, etc…). Depuis, il procède à une optimisation de l’apprentissage via une couche supplémentaire de formation utilisant la RLHF ou Reinforcement Learning from Human Feedback.
ChatGPT va servir à générer des textes de niveau humain, des traductions, mais aussi d’autres contenus : images, videos, constructions à partir modèles physiques (sequences et repliement des proteines !). Il peut servir à analyser et reconnaître des formes (medecine, reconnaissance faciale…)
L’interface du logiciel est très différente de celle d’un moteur de recherche: Avec ChatGPT Search, on a l’impression de participer à une véritable conversation, en ajoutant des informations à sa requête initiale. ChatGPT comprend et se souvient du contexte. Une fois la requête lancée, il rassemble les informations provenant de différentes sources pour fournir des réponses approfondies, et générer un texte ou un média.
Ces logiciels génératifs de texte ou image peuvent aussi répondre à une recherche sur le net, mais ils se distinguent des moteurs de recherche:
Chatbot versus moteur de recherche: ChatGPT Search vs Google Search
Le type de reponse de ChatGPT va être davantage construite, comme une synthèse. Par exemple, ChatGPT Search peut comparer des produits côte à côte, en soulignant les avantages et les inconvénients ou même en établissant un tableau comparatif simple pour vous aider à choisir.
En revanche, Google Search traite chaque question séparément, de sorte qu’il ne relie pas les réponses de la même manière et n’est pas prévu pour maintenir une conversation. On l’utilise plus pour obtenir des informations rapides, des informations visuelles ou des options de réservation et d’achat.
Inconvénients des Chatbot et moteurs génératifs basés sur IA:
Gourmand en ressources énergétiques, puissance de calcul et mémoire significatifs
Temps de calcul long, rendant difficile le traitement en temps réel
Absence de mise à jour en temps réel (n’a pas accès à Internet en temps réel)
peut produire des réponses biaisées ou limitées.
Pose des questions éthiques et juridiques, notamment en ce qui concerne l’utilisation de données protégées par le droit d’auteur et la confidentialité des informations.
sécurité et confidentialité
Moteurs de recherche et problème de confidentialité
Un moteur de recherche, c’est une entreprise, qui doit faire des profits.
Ses revenus viennent des annonceurs (sites commerçants) qui sont mis en avant par des publicités ciblées. C’est un mode de référencement payant, par opposition à celui naturel, réalisé à partir des contenus redactionnels (SEO).
Les moteurs de recherche mettent en avant une expérience plus personnalisée de l’internaute. Et ils ont besoin pour cela de récupérer vos données.
video: Les moteurs de recherche – Mediaprovence (juin 2019)
Limiter ses traces numériques: solutions
Ce que le moteur de recherche appelle des données échangées (entre services de la même entreprise), sont vos données personnelles.
Votre identité, vos contacts, la durée des appels, date, titres de vidéos, musiques consultées, historique des coord GPS, adresse IP, données des capteurs de l’appareil, requete lors des recherches, historique de navigation…
Pour limiter ses traces sur le Web, et reduire cette collecte de données qui vous concernent, vous pouvez:
dans le navigateur Mozilla : effacer les traces : bouton bibliothèqe, Historique, marques pages et plus encore > Historique > Effacer l’historique recent (cocher au choix : historique, historique des formulaires et des recherches, cookies et câche) ET Données > préférence des sites
paramétrer le navigateur : menu > Options > Vie privée et sécurité (Il y a plusieurs niveaux de sécurité). Dans Identifiants et mots de passe > afficher les mots de passe. Dans cookies et données > recherche la présence d’un cookie de connexion au site du lycée…
et Vie privée : blocage de contenus : toujours, afin de bloquer les contenus tiers qui peuvent ralentir la navigation ou distraire.
Le web permet à chacun de publier des informations sans contrôle préalable par une autorité. Cette revolution democratique amène la présence de fausses nouvelles (fake news) et le besoin de verification. Libération (désintox) et Le Monde (le blog des decodeurs) possèdent des espaces dédiés à la pratique, dédiant des journalistes à cette seule tâche.
Wikipedia est un exemple d’encyclopedie libre et participative, où des centaines d’internautes publient et relisent et effectuent des milliers de changement par heure.
aspects négatifs:
Le web et le droit d’auteur: besoin de protection grâce à des licences (creatice commun)
Les traces laissées de manière voulue ou non lors de sa navigation
la surveillance des individus sur le web
D’où l’importance d’un cadre juridique permettant de protéger les usagers, préoccupation à laquelle répond le règlement général sur la protection des données (RGPD).
Cout environnemental
Selon Google, toute requête sur son moteur de recherche consomme autant d’énergie qu’une ampoule de 60 watts qu’on allume pendant 17 secondes. Soit, en moyenne, une émission de 0,7 gramme de CO2.
1 mail simple émet 4 g CO2. 1 mail avec pièce jointe émet 35 gCO2, soit près de 10 fois plus !
Pour une requête sur ChatGpt : Une courte conversation (quelques interactions) avec le dernier modèle de ChatGPT émet environ 270g d’équivalent CO2 (eqCO2), soit près d’une tonne de CO2 par an pour dix échanges par jour.
Exercices
Construire une URL (Uniform Ressource Locator)
Pour accéder aux documents d’un serveur, il faut saisir une URL (une adresse) dans un navigateur.
Un ordinateur serveur héberge des dossiers et des fichiers. Le chemin vers un document est mis après l’adresse du nom de domaine dans l’URL.
Par exemple, pour atteindre fichier1.css, il faut saisir l’adresse :
http://nom_du_domaine.fr/dossier2/fichier1.css
exercice inspiré de la page web du site pixees.fr/informatiquelycee
Quelle est l’URL à saisir pour atteindre fichier4.js ?
Quelle est l’URL à saisir pour atteindre fichier6.html ?
Le web est un de ces services qui consiste à pouvoir naviguer sur des pages web reliées entre elles par des liens hypertextes.
Une brève introduction:
mooc SNT: Internet et le Web
le rôle du navigateur: présenter et rendre les pages interactives
histoire du web - Delagrave
Il existe plusieurs logiciels navigateurs (Mozilla, Chrome, Safari,…). Et pourtant, malgré cette diversité et ces évolutions du langage, ceux-ci vont interpréter ces fichiers et afficher les pages (presque) de la même manière car ils se réferent tous aux mêmes recommandations, qui sont les normes dictées par le w3c.
Une petite différence peut exister pour le rendu d’une même page, mais avec plusieurs navigateurs différents. Cela est du aux propriétés par défaut utilisées par le navigateur pour l’affichage des différents éléments html de la page.
Bilan: Le Web fonctionne avec des documents qui sont interconnectés par des hyperliens. Le web necessite d’utiliser un logiciel appelé navigateur qui sert à présenter les pages, surfer, mais aussi remplir des formulaires, interagir avec la page.
Cette navigation sur le web est possible grâce à la relation client-serveur du navigateur avec le serveur qui heberge la page. Ce serveur possède une adresse sur le net que l’on traduit de manière symbolique grace à l’URL. Cette relation necessite d’utiliser des protocole de communication, comme http.
Adresse d’une page web: URL
Uniform Ressource Locator: où est la page?
Une URL (Uniform Resource Locator) est l’adresse d’une page web.
Elle est composée de 3 parties:
http:// ou https:// qui correspond au protocole de communication client-serveur développé pour le web.
Un nom de domaine, souvent une marque, une entreprise, une association, …
un chemin qui pointe vers une ressource ou page précise.
la ressource
Par exemple, la page html que vous consultez, fait partie du domaine allophysique.com et se trouve à l’emplacement /docs/snt_2nde/pages/page4/web/index.html:
Do Not Track explore les différentes manières dont le Web moderne enregistre et traque nos activités, nos publications et nos identités.
Debut de la vídeo: je sais que où vous habitez et que vous avez une belle journée je sais que vous utilisez un PC... Comment fait le site pour savoir ceci ? Quelles informations ai-je envoyé (sans le vouloir) pour charger la page?
Client -> Serveur
Un système informatique fonctionne sur le modèle client-serveur : L’ordinateur client a besoin d’établir des connexions avec un ordinateur serveur pour une grande partie des services dont il a besoin (consulter une base de données, communiquer, ouvrir des pages internet, charger des vidéos…).
Une fois la connexion établie, l’ordinateur serveur lui répond en lui renvoyant les données necessaires.
modele client serveur
mode client-serveur. Un serveur peut repondre aux requetes de multiples clients
Le serveur lui repond en renvoyant un (des) fichier(s) qui constituent des fragments de page (en HTML, js, css, png, …). Ces fragments complètent la page, son contenu, son style, ses éléments interactifs, ou apportent des ressources (images, videos…). C’est le navigateur qui interprète ces fichiers (ces fragments de page) et assure l’affichage de la page.
Mais alors ici, le serveur connaissait des informations sur le client. Pourquoi?
Le protocole HTTP
Usage du navigateur
Le navigateur est le logiciel qui permet d’utiliser le Web. Il se connecte au serveur à l’adresse définie par l’URL.
Il envoie une requete pour demander la ressource à l’aide du protocole HTTP.
HTTP : HyperText Transfert Protocol, permet au navigateur de demander une page sur le reseau et au serveur de la transmettre.
Dans le protocole HTTP, une méthode est une commande spécifiant un type de requête, c’est-à-dire qu’elle demande au serveur d’effectuer une action. En général l’action concerne une ressource identifiée par l’URL qui suit le nom de la méthode.
(definitions issues de https://fr.wikipedia.org/wiki/Hypertext_Transfer_Protocol)
Le navigateur utilise souvent la méthode GET lors de l’envoi d’une requete:
observation de la requete GET à l'aide de l'outil reseau du navigateur
Contenu: données et metadonnées
Dans le fichier de reponse, il y a 2 parties :
• Une partie concerne l’en-tête : des métadonnées sur le document
• L’autre partie est constituée des données à afficher (balises HTML)
Du côté client, il y a aussi des métadonnées. C’est ici que l’on retrouve :
Information de la methode GET
url demandée (non de domaine de serveur
Accept (text/html, fr…)
Site depuis lequel la demande est effectuée
MAIS AUSSI, des informations partagées (et qui ne devraient pas l’être) qui devraient faciliter la session avec le site demandé : les cookies.
Champ d’en-tête
Signification
Exemple
Accept
Les types de contenu que le client peut traiter ; si le champ est vide, il s’agit de tous les types de contenu.
Accept: text/html, application/xml
Accept-Charset
Quels jeux de caractères le client peut afficher.
Accept-Charset: utf-8
Cookie
Cookie stocké pour ce serveur
Cookie: $Version=1; Content=23
Content-Length
Longueur en octets
Content-Length: 212
Content-Type
Type MIME: text/plain pour les fichiers texte, application/.. pour le reste
Content-Type: application/x_222-form-urlencoded
Date
Date et heure de la demande
Date: Mon, 9 March 2020 09:02:22 GMT
Host
Nom de domaine du serveur
Host: exemple.fr
Referrer
URL de la ressource à partir de laquelle la demande est faite (c’est-à-dire à partir de laquelle le lien a été créé)
Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/80.0.3987.132 Safari/537.36
reseau P2P
C’est un mode d’organisation sur internet où toutes les machines se comportent alternativement comme clients ou serveurs.
mode P2P. Chaque machine joue alternativement le rôle de client et de serveur
Ce mode a pu être utilisé pour partager illégalement des fichiers en infraction avec le droit d’auteur. La repartition des documents sur de multiples machines a compliqué les poursuites judiciaires.
Ce mode P2P connait un regain d’interet avec les Blockchains qui consistent à repliquer sur de nombreuses machines les preuves chifrées et vérifiables d’un ensembles d’informations enregistrées.
(monnaies virtuelles)
sécurité et confidentialité
Ce que le moteur de recherche appelle des données échangées (entre services de la même entreprise), sont vos données personnelles.
Votre identité, vos contacts, la durée desappels, date, titres de vidéos, musiques consultées, historique des coord GPS, adresse IP, données des capteurs de l’appareil, requete lors des recherches, historique de navigation…
Pour limiter ses traces sur le Web, et reduire cette collecte de données qui vous concernent, vous pouvez:
dans le navigateur Mozilla : effacer les traces : bouton bibliothèqe, Historique, marques pages et plus encore > Historique > Effacer l’historique recent (cocher au choix : historique, historique des formulaires et des recherches, cookies et câche) ET Données > préférence des sites
paramétrer le navigateur : menu > Options > Vie privée et sécurité (Il y a plusieurs niveaux de sécurité). Dans Identifiants et mots de passe > afficher les mots de passe. Dans cookies et données > recherche la présence d’un cookie de connexion au site du lycée…
et Vie privée : blocage de contenus : toujours, afin de bloquer les contenus tiers qui peuvent ralentir la navigation ou distraire.
Accepter ou refuser les cookies tiers. La liste :-o)
HTML
video - evolution des pages web 1990-2019
Document Web: HTML
Contenu et Structure
Le contenu des documents Web est rédigé en langage HTML (acronyme de Hypertext Markup Language). HTML est un langage interprété (par le navigateur). C’est un langage de description qui gère le contenu (le texte et les images), en ajoutant des éléments de structure, comme par exemple:
mettre le texte dans un paragraphe
mettre du texte en relief
insérer un hyperlien sur le texte
mettre un titre à la page, au paragraphe
…
Lire la video depuis 20' => 1min40'
Cette combinaison de contenu et de structure a été vue avec la création d’un document sous LibreOffice Writer. Ces documents ne peuvent toutefois pas servir à la navigation sur internet. Leur poids est trop important, et le code de la page n’est pas normalisé. On utilise pour la redaction de ces pages une combinaison de langages (html, css, js) qui seront rédigés de manière normalisée (recommandations du w3c), et interprétés de la même manière ou presque par tous les logiciels navigateurs.
Les éléments en HTML
Balises
Les élements sont décrits par des balises, comme par exemple, l’élément paragraphe p, est déclaré à l’aide d’une balise <p>. Toute balise ouverte doit être refermée, ici avec </p>. Et le contenu (souvent textuel), est mis entre ces deux balises:
exemple d'une balise paragraphe
Ces balises s’utilisent comme des parenthèses et peuvent être imbriquées. Une mauvaise imbrication de balises constitue une erreur.
Par exemple: Une imbrication correcte:
<body><div><h1>Wanted!</h1></div></body>
Une imbrication non correcte:
<body><div><h1>Wanted!</h1></body></div>
Les balises principale
Les balises sont les instructions en langage HTML des éléments structurants de la page web.
Les balises se distinguent entre celles qui n’ont pas d’attribut obligatoire, et celles qui en ont. Un attribut va ajouter des fonctionnalités à l’élément HTML, et modifier son allure ou son fonctionnement.
On peut ajouter des attributs à une balise. Cela permet de modifier son comportement. Par exemple, la balise de lien a prend un argument obligatoire qui est href, et qui pointe vers la ressource. Lorsque l’on clique sur le contenu (ce qui est affiché par la balise), on est dirigé vers cette ressource.
Exemple: En reprenant l’exemple initial, on souhaite maintenant créer un lien hypertexte sur l’un des mots affichés. On inclue la balise suivante dans le paragraphe:
Restauration
Le lien
Restauration
Et cela va rediriger sur la page de wikipedia: restauration française de 1814, lorsque l’on clique sur
Restauration
Cette page ne présentait pas de mise en forme particulière. Le code ne contenait pas de balises fermantes. Les pages n’étaient pas hierarchisées.
Mise en boîte
Avec la norme actuelle du HTML, les pages présentent un structure qui propose un parcours de lecture, un design. L’idée est de capter l’attention du lecteur le plus longtemps possible, de transmettre une information dans un certain ordre.
Et pour mettre en forme des éléments à différentes positions, il faut insérer les éléments HTML dans des “boîtes”.
D’où l’usage de balises dite “container”, qui vont permettre ces structures en lignes et colonnes, comme div, section, article, …
La boite principale sera l’élément body, qui contiendra toutes les autres.
Une représentation en arbre
Observons 2 exemples.
Dans le premier, les éléments de la page se mettent l’un sous l’autre. Ici, les balises ne présentent pas de hierarchie entre elles. Elles sont toutes au même niveau.
Dans ce deuxieme exemple: l’élément h1 est au même niveau de hierarchie que l’ensemble suivant, constitué de 2 colonnes. Tout cet ensemble sera mis dans un container div.
Les 2 colonnes contiennent pour la premiere, les éléments h2 et p, et pour la deuxieme, une image.
Chacune de ces 2 colonnes devront être mises dans un élément parent, un autre container div par exemple. Cela va amener la descrition suivante:
Le schéma suivant montre la position de ces boîtes dans la fenêtre:
L’image en forme d’arbre, montre la hierarchie (généalogie) entre ces éléments.
Dans l’exemple qui suit, on peut lire dans le script html que la balise html contient celles head et body. html est donc une balise parente de head et body. On peut représenter ces liens de parentée avec le diagramme suivant:
Script complet:
<html><head><linkrel="stylesheet"href="style.css"></head><body><div><h1>Wanted!</h1><h3>Have you seen this robot?</h3><imgsrc="robot.png"><p>Description: Height: 30cm, Colour: purple and orange, Arms: 4</p><p>If you have any information, please contact 6207 332 2310</p></div></body></html>
Exercice: A l’aide du script complet, poursuivre le diagramme représentant la hierarchie entre ces balises.
Les sigles « CSS » sont l’abréviation de « Cascading StyleSheets » ou « feuilles de styles en cascade » en français.
Le CSS vient résoudre un problème bien différent du HTML : en effet, le HTML sert à définir le contenu et la structure d’une page, à leur donner du sens.
Le CSS, lui, va servir à mettre en forme les différents contenus définis par le HTML en leur appliquant des styles.
Si votre navigateur affiche par défaut les contenus textuels que vous avez déclaré comme des titres en HTML en grand et en gras et à l’inverse les paragraphes en plus petit c’est justement parce que chaque navigateur possède sa propre feuille de styles. En fournissant nos styles CSS pour les différents contenus de notre page, nous allons donc pouvoir définir l’apparence de ceux-ci puisque les styles que nous allons fournir vont être considérés comme prioritaires par rapport à ceux du navigateur. C’est le principe du style en cascade (CSS)
Une déclaration CSS
Une déclaration typique est composée de trois parties :
un sélecteur,
une propriété,
une valeur
selecteur { propriete: valeur; }
La valeur de la propriété se met après le séparateur :.
Ces règles deviennent des déclarations lorsque celles-ci comprennent plusieurs couples propriété-valeur :Les règles sont alors séparées par un point-virgule ;, dans la même accolade:
selecteur{propriete1:valeur;propriete2:valeur;}
Exemple:
règles CSS associées à tous les éléments p de la page: caractères mis en gras (font-weight: bold) et entourés d'une bordure rouge (border: 2px solid red)
Le selecteur fait référence à un ou plusieurs éléments du document.
Selecteurs
Pour pouvoir appliquer un style à un contenu, il va déjà falloir le cibler, c’est-à-dire trouver un moyen d’indiquer qu’on souhaite appliquer tel style à un contenu en particulier.
En classe de SNT, le sélecteur, c’est l’élement HTML que l’on veut cibler.
Où met-on les déclarations CSS?
On cherche à créer le style suivant:
Il y a 3 possibilités pour écrire les règles CSS:
Soit directement dans la balise, avec l’attribut style. Exemple:
<divstyle="border:solid;"><pstyle ="color:#26b72b;>Le texte suivant sera affiché en VERT, qui est codée en hexadécimal avec #26b72b.</p></div>
Dans ce cas, seule la règle propriete:valeur; est écrite, pas le sélecteur.
Soit directement dans la page HTML, entre les balises style:
L’élément <style> peut être inclus dans l’élément <head> ou dans l’élément <body> du document et les styles seront appliqués. Toutefois, il est recommandé de placer les styles dans l’élément <head> afin de clairement séparer la présentation du contenu autant que possible.
Exemple:
<head><style>p{color:#26b72b;border:solid2px;}</style></head><body><p>Le texte suivant sera affiché en VERT, qui est codée en hexadécimal avec #26b72b.</p></body>
La méthode idéale consiste toutefois à utiliser des feuilles de style dans des fichiers externes et de les appliquer au document grâce à des éléments <link>:
<head><linkrel="stylesheet"href="style.css"></head><body><p>Le texte suivant sera affiché en VERT, qui est codée en hexadécimal avec #26b72b.</p></body>
C’est dans le fichier style.css que l’on mettra alors les déclarations css.
Le choix de la position du CSS est déterminé par l’ampleur du projet à définir, doit-on par exemple appliquer ces déclarations à toute la page, aux autres pages du site, …
introduction au CSS, video de la chaine Alphorm
Héritage
Comme vu dans le cours sur HTML, les éléments ont une hierarchie selon l’imbrication de leurs balises.
Par exemple, avec l’extrait de page HTML suivant:
<section><h1>Titre de la section</h1><div><p>Paragraphe 1</p><imgsrc="photo.jpg"></div><div><p>Paragraphe 2</p></div></section>
On a l’arbre du DOM:
arbre du DOM d'après l'extrait HTML
Les éléments enfants héritent les règles CSS de leur parent, à condition que ces règles leurs soient applicables.
Pour selectionner un élément particulier, il faudra le selectionner à partir de sa classe, un attribut qu’il faut rajouter à la balise de l’élément.
Ceci oblige à co-construire le fichier HTML et le fichier CSS, ce qui peut être parfois un vrai casse-tête…
Youtube - Mon probleme avec le CSS
Avec un attribut classe, le selecteur CSS fait reference à la valeur de classe. Le sélecteur utilise une notation avec un point devant la valeur de classe.
Exemple:
balise HTML
déclaration CSS
<p class="paragraphe_stylé">Mon paragraphe</p>
.paragraphe_stylé {font-family: arial; }
Dans le code HTML, la balise p que l’on veut styliser a l’attribut class. Et la valeur paragraphe_stylé pour valeur de la classe. Ce nom est librement choisi par le programmeur.
Dans le code CSS, le sélecteur est alors .paragraphe_stylé, avec un point devant le nom. La règle ne concerne alors QUE ce paragraphe. Si la déclaration avait été : p {font-family: arial; }, cela aurait concerné TOUT les paragraphes p de la page.
Projet de fin de chapitre: Réaliser un traceroute/ping vers plusieurs sites (France, Europe, autre continent), relèver les adresses IP et temps de latence, puis produire un schéma annoté expliquant le trajet des paquets (routeurs, protocole TCP/IP, adressage).
competences TP simulation d’un reseau d’ordinateurs: Lien
tour d’horizon de l’usage d’internet
culture numer
A quoi vous sert votre équipement informatique ?
Avant l’accès généralisé à l’internet, le particulier s’équipait d’un ordinateur pour faire du traitement de texte et des jeux.
Maintenant, c’est l’accès à internet qui est recherché, pour :
avoir accès à des informations distantes
s’informer, ou rechercher de l’information
apprendre, se former
communiquer entre personnes
divertissements interactifs (jeux, musique, vidéo à la carte)
commerce électronique (auquel participent même les institutions financières, mais aussi des services de braderie en ligne, entre particuliers, de consommateur à consommateur
commande d’un taxi ou d’un repas, avec suivi en temps réel du délai d’attente
autres services : téléformation, télémedecine, …
https://fr.surveymonkey.com/r/T8GSRTW
Quel est votre terminal ?
On entend par terminal, l’appareil que vous utilisez pour utiliser les services fournis par internet. Progressivement, l’ordinateur a reculé et a été remplacé par les smartphones, tablettes, assistant vocal ou montre connectées pour la plupart de ces services.
equipement le plus utilisé pour se connecter à internet en 2019
une utilisation nomade
Il y a une convergence des usages que l’on fait avec un ordinateur et un smartphone. Sauf qu’avec le smartphone, le reseau sans fil est un moyen d’avoir un bureau mobile.
Mais c’est aussi d’autres services : taxis connectés, des applications mobiles comme celles par exemple de parcmètres (bornes qui lisent les cartes de credit en effectuant un contrôle immédiat, ou qui rapportent l’expiration), les distributeurs de boisson connectés avec état des stocks, compteurs d’electricité…
Pour le client, la possibilité de lire un code barre et de mettre en relation avec une base de données. (les autres magasins, la composition, le meilleur point de vente…)
La géolocalisation offre de nombreuses possibilités, comme le conseil des restaurants à proximité. Les possibilités sont infinies.
Mais les activités principales liées à l’utilisation d’un smartphone restent la consultation de page à l’aide d’un navigateur, et l’utilisation de messageries ou des réseaux sociaux :
Proportion de la population qui utilise leur téléphone mobile pour ...
La communication par internet
Des formes de communication interpersonnelles : (entre 2 personnes ou plus)
Le mail a été la première manière de s’envoyer des messages, et reste aujourd’hui la forme la plus utilisée dans le milieu professionnel.
Il y a eu au démarrage un fort engouement des adolescents pour la messagerie instantanée (inspiré du programme talk de Unix); les chat rooms, salles de conversation autorisant un groupe de personnes à taper des messages visibles par tous. (sorte de bavardage). Les formes de communication ne s’y limitent d’ailleurs pas au texte, mais il y a des photos ou de courtes vidéos qui peuvent aussi y être partagées.
Les forums de discussion : où la communication ne fonctionne pas en temps réel, mais permet de poster un message que tous les membres peuvent lire
les applications de messagerie instantanée, avec la possible création de groupes
les applications de réseaux sociaux, qui diffèrent des forums par une communication plus immédiate et éphemère, mais aussi des messageries instantanée par la possibilité de naviguer sur le net, se focaliser sur certains types de médias (photo, video), de s’abonner à certains comptes, …
le peer to peer : communication entre systèmes homologues (pairs) : différents du modèle client-serveur. Les utilisateurs forment un groupe indéfini. L’échange se fait sur pied d’egalité et les rôles client-serveur ne sont pas assignés de façon fixe. Chaque utilisateur maintient sa propre base de données ainsi qu’une liste des autres personnes dans le voisinage participant au système. Jeux en réseau, courrier électronique sont d’autres exemples de peer to peer.
téléphonie, visiophonie, radio via internet.
Trouver plus de statistiques sur
La recherche d’informations sur le net
La recherche d’information passe le plus souvent par:
Sur des reseaux avec des sujets aux thematiques techniques, les échanges entre personnes ne génèrent pas de problemes.
Par contre, lorsque les sujets touchent à des domaines plus sensibles : religion, politique ou sexualité, les esprits s’enflamment et les messages peuvent devenir choquants, ou blessants.
Il y a 2 courants de pensée :
ceux qui prônent la tolérance
ceux qui pensent que certains messages doivent être censurés
D’ailleurs, les lois diffèrent ou s’opposent selon les pays.
Des personnes ont poursuivi en justice les opérateurs, les tenant pour reponsables du contenu qui circule sur les reseaux. Mais cela s’apparenterait alors à une censure et porter atteinte à la liberté d’expression.
Une autre source de désaccord, liée à l’utilisation du contenu des messages sur les réseaux sociaux, ou des traces de navigation concerne :
le droit respectif des employés et des employeurs
des universités et leurs étudiants
les gouvernements et leurs citoyens. Par exemple, le FBI avait mis en place un systeme d’espionnage des messages chez plusieurs fournisseurs d’accès afin de collecter des données interessantes. Le 4e amendement de la constitution americaine a mis fin à ce projet.
les entreprises et leurs visiteurs : les cookies, qui leur permettent de suivre leur activité et renseignent ceux qui y ont accès à certaines informations confidentielles comme les intérêts des visiteurs pour certains produits, leur mail, leur mot de passe, ou leur numéro de téléphone mobile.
Restez informé : Les droits pour maîtriser vos données personnelles !
<figurerestez informé : la CNIL
* paramétrer
maitrisez l'accès à vos données : la CNIL
fausses informations
Les reseaux permettent d’envoyer des messages anonymes. On peut ainsi dénoncer quelqu’un sans risquer de represailles. Mais, heureusement, dans une societé democratique, une accusation ne fait pas preuve et toute personne a le droit d’être confronté à son accusateur.
Internet permet la diffusion d’informations de manière virale :
Cela peut contribuer à un reveil de l’opinion publique :
voir l’enchainement des évenements pendant les elections en Espagne : 11 mars 2004, l’attentat de la gare de Madrid. Le gouvernement du président Aznar manipule l’information pour laisser croire que la responsabilité de cet attentat incombe à l’ETA, un parti politique clandestin. Mais rapidement, une chaine de messages (twitter ou autres reseaux sociaux) entre citoyens met au jour ce que l’on pourrait apparenter à un mensonge d’état. Aznar perd alors dans la foulée les élections legislatives qui se tiennent 2 jours plus tard. https://www.monde-diplomatique.fr/2004/04/RAMONET/10895
voir soulèvement du 15 mai 2011 en espagne : parti politique d’initiatives populaires (les indignados)
Ou la manipulation de l’opinion publique avec des nouvelles fausses (elections de Donald Trump aux états-unis en 2016).
Important : Toujours vérifier une information. Quelle est sa source ? Quelle est la qualité du média ou de la personne qui la diffuse ?
L’internet c’est aussi aussi des problemes de securité, avec de nombreuses données non chiffrées, ce qui ouvre la possibilté à de nombreux méfaits :
recevoir du courrier electronique non sollicité (spam). Notre adresse est revendue à des sociétés qui s’adonnent au marketing sauvage.
recevoir des macros avec virus en pièces jointes
le vol d’identité
Sur internet, il y a autant de personnes mal intentionnées que dans la vraie vie
Mais le chiffrement est couteux pour les fournisseurs d’équipement et de logiciels.
Un autre problème de sécurité vient d’une technique que l’on appelle le phishing : le pirate se fait passer pour un organisme bancaire, un assureur, un opérateur de téléphonie… La technique est souvent celle-ci :
Vous recevez un mail de cet organisme, vous demandant de cliquer sur un lien qui devrait vous rediriger vers le site de cet organisme.
Seulement, lorsque vous cliquez, vous pouvez constater que le nom de domaine n’est pas rigoureusement identique à celui de l’organisme original.
Ainsi, l’URL https://twiter.com(le faux site, dont le nom de domaine est twiter) n’est pas identique à https://twitter.com(le vrai site, de nom de domaine twitter).
un exemple de phishing
detail du lien
Ensuite, on vous demande:
vos identifiants de connexion,
ou coordonnées bancaires, numéro de carte de crédit ou autre, que vous choisissez intentionnellement (et malheureusement) de donner, sans vous méfier.
Il existe heureusement des recours, au cas où cette mésaventure vous arrive, mais cela vous aura porté préjudice. Le mieux est de toujours adopter une posture de doute lorsqu’un tel mail vous parvient…
La diffusion libre d’ouvrages artistiques
L’utilisation d’un service de téléchargement ou de streaming illégal entraine la violation des droits d’auteur avec la transmission de musique et video numerique.
L’objet étant numérique, cela ne constitue pas à proprement parler d’un vol lorsque l’on s’en procure une copie. On peut d’ailleurs en réaliser un nombre illimité de copies numériques. Un fichier musical, une vidéo, une image ou un livre numérique constituent des biens non rivaux. Mais l’existance de droits d’auteurs empêche normalement la libre diffusion de l’oeuvre, et les personnes qui pratiquent cet échange enfreignent la loi.
Le coût énergétique de l’utilisation d’internet
Un article interessant du CNRS montre que l’usage de services dits dématérialisés n’est pas sans conséquences au niveau de la consommation énergétique.
Etre présent sur le web
Faut-il créer son site web ou être présent sur les reseaux sociaux?
Les deux:
La bonne pratique est de créer du contenu sur votre site ou page web et ensuite de le diffuser sur les réseaux sociaux. En effet, la communication sur les réseaux sociaux est éphémère. Si votre tweet ou votre post n’est pas vu au moment de sa publication, ce contenu sera perdu tandis que le contenu sur votre site internet restera et contribuera au bon référencement naturel de celui-ci.
Une première idée naïve : tout usage du numérique met des machines en connexion, et qui échangent des données.
communication avec 2 ordinateurs
Ce modèle simpliste de réseau va devenir irréalisable lorsque celui-ci contiendra de nombreux ordinateurs :
grand nombre de connexions (et de liaisons physiques) au départ de chaque ordinateur
grand nombre de ports utilisés
Internet ne constitue pas un graphe complet, c’est à dire un reseau dans lequel chaque machine est directement connectée à une autre.
Il faudra d’autres éléments pour connecter les ordinateurs entre eux.
Reseau d’ordinateurs
Qu’est ce qu’un système informatique ?
Un système informatique fonctionne sur le modèle client-serveur :
Les parcs informatiques des écoles, universités, et entreprises ont leur activité qui dépend d’informations partagées sur leur réseau. (gestion des salles, ressources, identité des étudiants, des clients, les stocks, la comptabilité, les états financiers,…). En conséquence, une panne informatique ne leur permettrait plus de fonctionner. C’est pour cette raison que les ordinateurs doivent être connectés, que ces informations doivent être distribuées; que l’information doit être accessible, même si l’un des ordinateurs est en panne.
Un système informatique est alors constitué :
d’une ou plusieurs base(s) de données
d’ordinateurs serveurs qui stockent les bases de données
d’ordinateurs clients : des ordinateurs plus simples, et qui doivent avoir accès aux ressouces.
local area network (LAN)
des services diversifiés
Un réseau d’ordinateurs peut aussi servir à fournir des services de communication :
courrier électronique
outils de collaboration (redaction à plusieurs)
visioconférence
la conclusion d’affaires par voie électronique, commandes en temps réel
logiciel partagé
C’est l’utilisation d’un serveur partagé dans le réseau qui permet d’acceder à ces services.
Certains de ces services peuvent aussi être fournis par un serveur sur un réseau externe, accessible depuis internet. C’est ce que l’on appelle le cloud : la livraison de ressources et de services à la demande par internet.1
Un réseau d’ordinateur peut aussi servir à partager du matériel (une imprimante), ou une connexion internet (le routeur). (voir note en bas de page sur la configuration d’un reseau local2)
Le commutateur (switch) et le routeur
Les appareils ne sont pas forcément connectés directement, mais peuvent l’être au moyen d’un switch. (concentre les liaisons et possède une table de routage avec les adresses mac des ordinateurs reliés).
les switchs (commutateurs) peuvent lire les adresses matérielles des paquets entrants afin de les transmettre à la destination appropriée.
Les réseaux sont alors reliés entre eux par un routeur
réseaux d'ordinateurs
Sur cette image, plusieurs sous-reseaux sont reliés par des routeurs. Par contre, l’appareil qui interconnecte les machines dans un même sous-reseau est un switch.
le routeur est l’appareil disposant plusieurs adresses IP, une adresse par interface (voir plus loin). Il fait office de passerelle entre les périphériques sur un réseau local (LAN) et Internet. Dans un réseau de réseaux, cette machine doit posséder plusieurs interfaces (plusieurs cartes réseau), chacune reliée à un réseau. Son rôle va être d’aiguiller les paquets reçus entre les différents réseaux.
Un système réparti permet de partager des ressources, données et logiciels.
Avec un réseau local d’ordinateurs, qui peut constituer un système réparti, l’utilisateur se trouve devant la réalité des machines et leurs caractéristiques diverses, la varieté des équipements, et de leur système d’exploitation; pour executer un programme sur une machine distante, l’usager doit ouvrir une session. La maitenance d’un reseau local demande une bonne connaissance de tous ces matériels.
Et si l’un des ordinateurs tombe en panne, les autres ordinateurs risquent de s’en apercevoir (base de donnée inaccessible, etc…).
Définition: Un système réparti est un système qui vous empêche de travailler quand une machine dont vous n’avez jamais entendu parler tombe en panne.
Des exemples de systèmes répartis: un centre de documentation, bibliothèque, reseau de lycée, contrôle et organisation d’activité en temps réél,…
Pour approfondir : (Wikihow) comment configurer son réseau local ? 2
Lorsque l’on utilise internet, on ne voit plus cette variété d’équipement.
le système distribué est un ensemble d’ordinateurs indépendants, présenté à l’utilisateur comme un système unique cohérent. Souvent une couche logicielle intermédiaire appelée middleware située au dessus du système d’exploitation est responsable de son implémentation.
Un exemple est le web dans lequel toute information apparait comme un document. C’est donc un logiciel élaboré au dessus du réseau, qui nous fait oublier la variété des supports utilisés pour transmettre les données (Serveur, Adsl, Box, wifi, bluetooth…).
Définitions
Un système distribué: C’est un ensemble d’ordinateurs indépendants qui apparaît à un utilisateur comme un système unique et cohérent
Internet n’est pas un réseau d’ordinateurs. C’est un réseau de réseaux.
Le web, c’est un système distribué opérant au-dessus d’internet.
Caractéristiques physiques : canal de transmission:
1. reseau local
Deux critères permettent de les caractériser : la technologie de transmission utilisée, et leur taille.
Dans un reseau local, les supports de transmission des données peuvent être :
cable ethernet
wifi (ondes EM)
bluetooth (ondes EM à courte portée)
2. reseau internet
Une fois sorties du reseau local, les transmissions peuvent se faire par:
Remarque: L’utilisation d’internet demande un abonnement à un FAI.
Adressage des machines.
adressage dans un reseau local: MAC
une adresse MAC (Media Access Control), appelée également adresse Ethernet, est l’adresse physique d’une interface (carte réseau, wifi, …). Chaque adresse MAC est normalement unique au monde et fournie par le fabricant de l’interface.
Cette adresse est constituée de 6 octets, soit 12 caractères hexadécimaux, comme par exemple:
$$01:b8:43:c4:85:a3$$
Un ordinateur qui reçoit un message par l’une de ses interface, va lire si l’adresse MAC est bien la sienne. Sinon, c’est que le message ne lui est pas destiné: il détruit alors le message.
Dans un reseau local où les machines sont interconnectées via un switch: Pour envoyer la trame vers la bonne machine, le switch se sert de l’adresse MAC destination contenue dans l’en-tête de la trame.
Il contient en fait une table qui fait l’association entre un port du switch (une prise RJ45 femelle) et une adresse MAC. Cette table est appelée la table CAM.
adressage IP
une adresse IP est un identifiant numérique unique attribué à chaque appareil (appareils mobiles, ordinateurs, routeurs, imprimantes, consoles de jeux, etc.) connecté à un réseau TCP / IP comme Internet. Plus précisemment, c’est l’identifiant de la carte reseau, reelle ou virtuelle.
Chaque dispositif peut se connecter grâce à cette adresse IP à d’autres périphériques et partager des informations. Il s’agit du Protocole Internet (IP).
Question: Est-il possible de connaître l’emplacement de mon ordinateur (smartphone, …) en connaissant son adresse IP?
En principe, non, pas exactement, car mon dispositif possède une adresse IP privée… Il existe 2 types d’adresses IP:
Adresse IP privée: 2 machines peuvent avoir la même adresse privée à condition qu’elles soient sur 2 reseaux privés distincts. Pour une machine dotée d’une adresse privée qui doit accéder à internet, une traduction de son adresse privée en adresse publique est nécessaire. C’est le mécanisme NAT (Network Adress Translation) qui assure cette fonction. Ce mécanisme de traduction d’adresse réseau se fait par la passerelle, qui se situe à l’interface entre les réseaux privés et les réseaux publics. Elle est aussi nommée routeur (gateway). Une passerelle possède au moins 2 interfaces reseau.
adresse IP publique: adresse attribuée aux machines connectées sur Internet. Ce sont les FAI qui sont autorisés à affecter des adresses publiques. Ces adresses sont uniques au niveau mondial. L’essor constant d’internet au niveau mondial fait que l’on migre progressivement de la norme IPv4 vers IPv6. Ce sont deux protocoles réseau de la couche 3 du modèle OSI (Open Systems Interconnection).
IPv4
Ces adresses IP constituées de 4 nombres sont les plus répandues à l’heure actuelle, on les appelle IPv4.
Un exemple d’adresse IPV4: (exprimée par 4 nombres decimaux 0-255)
$$192.168.0.10$$
Bien que codés sur 32 bits (4 octets), leur nombre se révèle assez limité : il n’y a en effet “que”
$$256×256×256×256$$
possibilités d’IP, soit
$$256^4=4\phantom*294\phantom*967\phantom*296$$
(plus de 4 milliards). Ce nombre a l’air grand, mais on finira prochainement par l’atteindre avec la multiplication des ordinateurs et des serveurs reliés à Internet.
C’est pourquoi ces IP ont vocation à être remplacées par un nouveau système : IPv6 (8 groupes de 2 octets)
IPv6
Ce sont des adresses IP codées sur 128 bits, soit 16 octets, ou 32 caractères hexadecimaux.
La nouvelle forme d’IP, que l’on va rencontrer de plus en plus, a la forme suivante : (exemple)
$$1703:01b8:43c4:85a3:0000:0000:a213:bba7$$
Leur nombre est d’environ 10^29 fois plus important que pour les adresses IPv4.
DNS, IP et URL
Lorsque l’on demande un service sur internet, on ne saisit pas http://adresse IP mais http://URL de la page depuis la barre du navigateur. Il y a alors plusieurs étapes avant d’obtenir une ressource du serveur:
Le navigateur demande l’adresse IP correspondant au domaine mentionné dans l’URL. Il demande ce service à un serveur DNS.
le DNS: un enorme repertoire contenant les adr IP
Le navigateur se présente alors au serveur, qu’il arrive à joindre grace à son adresse IP.
Une fois la connection établie, le navigateur envoie sa requête, qui est souvent la demande d’une page internet.
Le serveur lui repond en lui envoyant la ressource demandée.
modèle client-serveur
En pratique, la ressource n’est pas envoyée en entier par le serveur, mais par petits morceaux. Cela rend l’utilisation d’internet plus efficace. (voir aussi le cours sur
le modele OSI et le protocole TCP
)
le protocole IP: c’est lui qui permet de se connecter à un autre ordinateur. Il gère l’adressage.
le protocole TCP: permet d’envoyer les paquets d’un ordinateur vers un autre ordinateur. Il gère le routage et l’interconnexion des différents réseaux.
Le cloud : désigne le stockage et l’accès aux données par l’intermédiaire d’internet plutôt que via le disque dur d’un ordinateur. Mais aussi des services rendus par des logiciels hébergés côté serveur. ↩︎
Systèmes répartis: Ce sont des systèmes pour lesquels les ordinateurs mis en reseau ont un couplage fort. Des exemples de systèmes répartis: un centre de documentation, bibliothèque, reseau de lycée, contrôle et organisation d’activité en temps réél,… ↩︎
Système distribué: Les ordinateurs du reseau ont un couplage faible, et communiquent par echange de messages de manière asynchrone. La difficulté de mise en oeuvre d’un algorithme sur un système distribué, est que l’on n’a pas connaissance de l’état global du système (routage sur internet). ↩︎
circulation des données
Video SNT: les protocoles
Video SNT: Internet, TCP-IP un protocole universel ?
Constitution du reseau internet
Réseau local
Dans un réseau local, les ordinateurs sont interconnectés par un switch et peuvent communiquer entre eux par l’intermédiaire d’un routeur. C’est aussi le routeur qui fait passerelle vers internet.
reseau local et internet
réseau internet
Internet est un réseau de réseaux qui interconnecte toutes les machines à l’échelle mondiale.
En pratique, ce sont les routeurs des réseaux qui sont interconnectés. Lorsqu’un routeur reçoit une requête d’une des machines de son réseau, adressée à une machine qui n’appartient pas à son réseau, il se réfère à une table de routage d’internet pour expedier la requête. Il envoie alors la requête à un autre routeur.
Routeur et routage
Le routeur: c’est une machine qui a pour rôle de communiquer avec d’autres machines.
Les routeurs s’occupent du routage sur internet, c’est à dire du meilleur choix de route selon les renseignements dans leur table de routage. Le but est de faire circuler les données, sans que celles-ci occupent trop longtemps le reseau, par les voies les plus rapides.
Chaque routeur est identifié par une adresse IP. Il possède une table de routage qui lui permet de choisir la bonne liaison entre les 2 machines qui veulent communiquer.
Cette table de routage identifie les ordinateurs de manière unique par leur adresse IP : Un code binaire à 32 bits (norme IPv4) ou 128 bits (norme IPv6).
Dans l’exemple ci-dessous, les données qui circulent du client vers le serveur vont probablement emprunter des chemins différents : certains passeront par les reseaux d’accès E, A, B et D, alors que d’autres emprunteront les reseaux E, A, C et D. Les routeurs par lesquels passent ces données seront aussi différents dans un même réseau d’accès. Le calcul de l’itinéraire est réalisé de manière dynamique, par les routeurs eux-même, en fonction du trafic.
Le trajet possible entre les 2 machines n’est pas unique :
Les données peuvent circuler en sous plusieurs formes et à travers différents canaux, ce qui modifie leur vitesse et leur débit :
Fibre optique : 100 Mo/s
Adsl : 5Mo/s
4G: 10 Mo/s
Wifi : 10 Mo/s
Bluetooth : 0,5 Mo/s
Comment utiliser le reseau Internet?
Pour naviguer sur internet, votre machine va communiquer avec d’autres serveurs. Cette communication met en jeu plusieurs protocoles, dont les principaux sont DNS, HTTP, IP et TCP.
Client – serveur
la description du reseau sous-entend un mode de fonctionnement client-serveur
Client : demande une ressource
Serveur : heberge et fournit la ressource
Il existe plusieurs niveaux de description des echanges entre client et serveur ce qui amène à utiliser un modèle en couches (TCP/IP).
Dans chaque couche de ce modèle, des algorithmes sont mis en œuvre et chaque couche s’occupe d’une partie de la transmission.
Par exemple, au niveau du client, le navigateur s’occupe de la resolution DNS puis de l’établissement du contact avec le serveur (HTTP)
Les autres couches vont s’occuper du routage et de sa fiabilisation.
Algorithme : une suite ordonnée et non ambigüe de commandes ou instructions. C’est une séquence d’ordres
la resolution DNS
C’est l’une des étapes du protocole TCP/IP. Au cours de celle-ci, l’ordinateur client qui cherche à se connecter à un ordinateur serveur. Il va demander au serveur DNS de lui convertir l’adresse symbolique (URL) en une adresse IP, celle du serveur à joindre. Puis, une fois qu’il connaît l’adresse ip, il envoie une requête HTTP à l’ip correspondante afin que le serveur lui retourne la page.
Il y a une correspondance entre l’adresse symbolique et l’adresse IP. Lorsque l’on demande à notre machine de joindre celle d’adresse symbolique musee-orsay.fr, il y a un protocole qui se charge de renseigner l’adresse IP correspondante, afin que les machines puissent communiquer entre elles. C’est le protocole de résolution DNS.
Cette résolution DNS est réalisée :
D’abord grâce au fichier host.txt de notre machine
Puis, si l’adresse n’est pas dans le fichier, par le serveur DNS
Le protocole HTTP
Ce protocole HTTP est initié par le client, le navigateur (Mozilla, Chrome, …).
Une fois la connexion établie, vous allez pouvoir charger la page Web depuis l’ordinateur serveur.
adresse IP et adresses symboliques
Les adresses IP identifient les machines par un numero (sur 32 bits pour l’IPV4, et 128 bits pour l’IPV6) et leur permet de communiquer entre elles. Le problème est que le format de cette adresse n’est pas très intelligible pour un humain. C’est pour cela que les sites et les programmes hébergés sur les serveurs possèdent aussi une adresse symbolique (nom d’hôte).
Par exemple, l’adresse IP 207.142.131.245 est celle de Wikilivres.com (son nom d’hôte correspondant).
Les tables de correspondance : nom d’hôte <=> adresse IP sont tenues par des serveurs appelés DNS (domain name system). C’est à ce serveur DNS que votre routeur se réfère lorsque vous saisissez une adresse symbolique (une URL) dans la barre de navigation de votre navigateur.
Une fois la résolution DNS réalisée, les machines entrent en contact grâce à leurs adresses IP. Ce sont des étapes du protocole IP.
Comment sont transmises les informations numériques ?
Le protocole TCP Internet manipule deux types d’information : les contenus envoyés et les adresses du destinataire et de l’émetteur. Ces deux types d’information sont regroupés dans des paquets de taille fixe, de façon uniforme et indépendante du type de données transportées : texte, images, sons, vidéos, etc.
Ces données sont rassemblées dans des trames de 1500 octets. La plupart du temps, les données à envoyer sont de taille supérieure à 1500 octets, et il faut plusieurs trames.
decoupage de l'information numérique en plusieurs datagrammes
C’est le protocole TCP qui gère ce découpage, et rajoute des informations pour pouvoir renvoyer les paquets perdus en chemin (grâce à un accusé de reception), et remettre les paquets dans le bon ordre. Un code de vérification est également ajouté au paquet, pour vérifier s’il est conforme à l’original, et non corrompu en chemin.
TP: comprendre le protocole TCP en jouant :
reseau local et chemin entre routeurs : interstice.info
> Vous devez perturber le transport des paquets afin d’empêcher la reconstitution du message. Au fur et à mesure que vous passez les niveaux, l’ordinateur trouve de nouvelles stratégies pour y parvenir. Vous pouvez : retarder les paquets, les corrompre, ou les détruire.
Problème de libre accès au réseau internet et cybersécurité
Utilité des noms de domaine
Une bonne pratique est de lire les noms de domaines dans la barre d’adresse afin de s’assurer que l’on navigue vers le BON site. Une des attaques les plus classiques sur le net est le Phishing
On pourra consulter la video suivante:
phishing et noms de domaine - arsen.co
Naviguer en https
https est la version securisée pour l’echange de données sur internet. Lorsque vous demandez à charger une page sur internet (on dit que vous demandez une ressource), les etapes sont les suivantes :
Resolution DNS
Contact avec le serveur grace à l’adresse IP et le nom de domaine du site internet
Echange des clés de chiffrement
Le client demande la page web
Le serveur lui retourne la page
Le client envoie des données
Le serveur traite les données
…
En italique : les echanges chiffrés.
Risque (faible): si le flux de données est capturé: il est possible de connaitre le nom de domaine consulté, mais pas le contenu ni l’adresse de la page consultée sur le site.
Censure sur internet
Blocage DNS
Le blocage DNS consiste à empêcher la résolution d’un nom de domaine en adresse ip. On peut vérifier depuis la France si certains sites sont inaccéssibles pour un pays qui pratique la censure d’internet. Sur le site experte.com
page du site experte.com
Fonctionnement du site: envoi de l’URL sur l’un de ses serveurs hebergés dans les pays considérés. Test avec des pays pour lesquels l’internet est libre, afin de s’assurer que le domaine fonctionne bien.
page du site experte.com
exemple de blocages
Ce blocage est facilement contournable en utilisant un serveur DNS alternatif.
Blocage par adresse IP
Dans le cas d’un blocage ip, c’est directement l’adresse ip du site web qui est bloquée par le FAI, ou bien par un logiciel installé sur un noeud de routage (Proxy).
Dans de nombreux pays, les FAI sont contraints par leur gouvernement d’effectuer régulièrement un filtrage et une censure d’Internet. Ce type de blocage n’est pas sans poser de problème puisque si plusieurs sites sont hébergés sur la même adresse ip, comme dans le cas d’un hébergement mutualisé, l’ensemble des sites se retrouvent inaccessibles.
Néanmoins, dans le cas d’un tel blocage, il existe des solutions, comme d’avoir recours à un tunnel chiffré, tel qu’un VPN.
Utiliser un VPN
Le VPN assure un tunnel pour acheminer les données, chiffrées dès que la connexion est établie.
La procédure est la suivante:
Connection au serveur VPN
Resolution DNS pour le site demandé
Contact avec le serveur..
Echange des clés
;;;
En italique : les echanges chiffrés.
La connexion au VPN ajoute une securité supplémentaire, avec un 2e chiffrement, et l’effacement du nom de domaine consulté.
TP simulation d'un réseau
TP simulation reseau
Un reseau, c’est quoi? C’est un système constitué de machines reliées ensembles (machines de tout genre: ordinateur, imprimante,…). Elles ont une adresse IP.
L’adresse IP (Internet Protocol) identifie un périphérique à l’intérieur d’un réseau. A l’intérieur de ce réseau elle est unique.
Les outils utilisés en simulation ne fonctionnent pas tous en mode réel, à partir de votre propre ordinateur du lycée, à cause de restrictions nécessaires pour des problèmes de sécurité.
TP Filius 1 : faire communiquer 2 ordinateurs (durée indicative: 10 min)
Lancer le logiciel Filius.
On réalise un premier réseau simple de 2 ordinateurs reliés par une seule ligne.
Disposer les 2 ordinateurs comme présenté sur la video.
Modifier les adresses IP de ces ordinateurs pour avoir, dans l’ordre:
192.168.0.1
192.168.0.2
Remarque: Souvent, dans un même reseau, les 3 premiers octets de l’adresse IP des machines sont identiques. (ici: 192.168.0). Seul le dernier octet change. Pour l’une des machines, ce sera .1, pour la suivante .2, etc…)
Relier ces ordinateurs
Installer les logiciels utiles pour faire communiquer ces machines. Pour faire cela: Démarrer la simulation:
Puis faire un double clic sur chacune des machines, et installer le logiciel ligne de commandes.
console d'installation de logiciels
tester alors les commandes suivantes depuis la machine M1:
ipconfig : vérifier la correspondance de l’adresse IP de la machine M1
ping 192.168.0.2 : pour établir et tester une connexion avec la machine M2
traceroute 192.168.0.2 : pour établir le trajet qui mène jusqu’à M2
Tester alors les commandes ping et traceroute vers une adresse de machine inexistante dans le réseau. Par exemple 192.168.0.3
Qu.1a: comment voit-on si le chemin vers une machine du reseau existe? Quelle information lit-on dans la console?
modifier le réseau et mettre 3 ordinateurs reliés à un switch (un connecteur) : voir la vidéo pour explications
revenir en mode conception du reseau (bouton avec le marteau)
commencer par supprimer le cable (clic Droit sur le composant => Supprimer)
ajouter l’ordinateur M3. Modifier son IP en 192.168.0.3. Relier ces machines à l’aide d’un switch.
tester alors la commande de traceroute entre M1 et M3
Qu.1b: Pourquoi a-t-on besoin d’un switch dans un réseau à 3 ordinateurs?
TP Filius 2 : créer un reseau de type lycée (durée indicative: 20 min)
On cherche maintenant à créer un système de 2 sous-réseaux locaux. Ces reseaux auront pour adresses: 198.168.0.0 et 192.168.2.0
C’est à dire que toutes les machines du réseau 198.168.0.0 auront en commun les 3 octets 198.168.0 et toutes les machines du reseau 198.168.2.0 auront en commun les octets 198.168.2.
Le sous-réseau 192.168.2.0 comportera un switch et 3 ordinateurs M4, M5 et M6. Ces machines auront pour adresses IP:
192.168.2.1
192.168.2.2
192.168.2.3
Votre système devrait ressembler à l’image suivante:
systeme de 2 sous-reseaux sans routeur
Tester alors la commande ping depuis la machine M1 vers celle M6 du 2e sous-reseau.
Qu.2a:: La machine M6 est-elle accessible depuis M1? Pourquoi?
Modifier le système en ajoutant un routeur:
clic droit sur le Switch2 : faire supprimer tous les cables
ajouter le routeur
paramétrer le routeur:
clic sur le routeur
renseigner les adresses des 2 reseaux sur l’interface du routeur:
192.168.0.254 du côté du reseau 192.168.0.0 (à gauche)
192.168.2.254 du côté du reseau 192.168.2.0 (à droite)
adresses des reseaux
cocher routage automatique:
option routage automatique
Pour chacun des ordinateurs du sous-reseau 1, M1, M2, M3, renseigner l’adresse de l’interface reseau 1 du routeur: mettre 192.168.0.254 dans le champs passerelle. Ce sera l’adresse IP de la carte reseau du routeur, du côté du reseau 192.168.0.0 (on met 254 à la place de 0 pour l’adresse routeur).
renseigner l'adresse reseau pour chaque ordinateur
Même travail pour M4, M5, M6: renseigner la passerelle 192.168.2.254
refaire le cablage
Qu.2b: Pourquoi le routeur de votre système informatique possède t-il 2 adresses IP?
Qu.2c: Démarrer le système et tester alors la commande ping de M1 vers M6, puis de M6 vers M1. Que constatez-vous? Pourquoi?
Qu.3a. Représenter sur votre feuille le reseau en ne dessinant que les ordinateurs n°1 et n°15, ainsi que tous les routeurs traversé (plus court schemin entre M1 et M15).
Qu.3b. Indiquer sur le schéma, pour chaque routeur, l’adresse passerelle que le message de M1 vers M15 va emprunter.
Lancer la simulation
Prendre connaissance de l’adresse IP de l’ordinateur n°15
Depuis l’ordinateur n°1: Lancer le logiciel Ligne de commande
Faire: traceroute suivi de l’adresse IP de la machine 15
Repérer alors quels sont les adresses passerelles empruntées par les données entre ces 2 ordinateurs.
Qu.3c. Quel est le nombre de sauts entre M1 et M15? Est-ce que le nombre de sauts effectués vous semble cohérent?
Qu.3d. S’agit-il des mêmes adresses passerelles lorsque la machine M15 envoie un message à M1? Vérifiez le par une expérience.
Table de routage
Revenir en mode edition (marteau) : cliquer sur le routeur A
Dans l’onglet général : décocher l’option : routage automatique
Aller dans l’onglet table de routage (forwarding table):
table de routage du routeur A
Q3e : cartes reseaux du routeur:
Hormis l’interface 127.0.0.1 : Combien d’interfaces différentes possède le routeur? (colonne NIC, next interface connection)
Quels sont les 3 réseaux auquel ce routeur est directement relié ? Donner leur adresse IP.
Compléments théoriques sur les adresses des machines
L’adresse IP(Internet Protocol) identifie un périphérique à l’intérieur d’un réseau. A l’intérieur de ce réseau elle est unique.
Une adresse (IPv4) est constituée de 4 nombres binaire de 8 bits chacuns (32 bits), comme par exemple:
$1100 0000.1010 1000. 0000 0000. 0000 0001$
Pour rendre la lecture plus facile, les séries de 8 bits seront traduites en leur valeur décimale correspondante, comprise entre 0 et 255 (voir le cours codage des nombres).
L’adresse binaire vue plus haut sera alors traduite en :
$192.168.0.1$
L’adresse possède 2 parties:
une partie identifie la machine
une autre partie identifie le reseau
Masque de sous-reseau
Masque de sous-reseau: c’est une serie de valeurs avec des 255 ou 0, ou autre sur le(s) dernier(s) octet(s).
La valeur correspondante binaire début donc par une série de 1, marquant les positions relatives à l’adresse reseau dans l’adresse IP.
Par exemple: L’adresse machine suivante est constituée d’une première partie reseau, les 24 premiers bits, puis de l’adressage machine dans le reseau (8 derniers bits):
$1100 0000.1010 1000. 0000 0000. 0000 0001 / 24$
Le masque de sous-reseau est alors:
$1111 1111.1111 1111. 1111 1111. 0000 0000$
Que l’on peut aussi écrire:
$255.255.255.0$
Machines appartenant à un même reseau
Definition: Deux machines sont sur le même réseau si et seulement si, la partie réseau de leur adresse IP est identique.
Les derniers caractères /24 correspondent au masque de sous-reseau. Ils signifient que le reseau contenant la machine a une adresse codée sur les 24 premiers bits (192.168.0). Et que les 8 derniers bits constituent l’adresse de la machine dans ce reseau (il s’agit donc du .1 final).
IPv6
Pour la norme IPv6, ce nombre est sur 128 bits, soit 16 octets.
Exemple d’adresse IPv6 exprimée en hexadécimal (32 caractères):2001:0db8:3c4d:0015:0000:0000:1a2f:1a2b
classes d’adresse IP
classe A : adresses IP comprises entre 0.0.0.0 et 127.255.255.255 masque 255.0.0.0 : on ne peut avoir qu’une toute petite partie sous-reseau mais beaucoup d’adresses machines. Un petit reseau de beaucoup de machines.
classe B : 128.0.0.0 à 191.255.255.255 masque sous-reseau de 2 octets : on met autant de machines que de sous reseaux.
classe C : masque sous-reseau de 3 octets: beaucoup de sous-reseaux et peu de machines.
Sur un reseau, deux adresses sont deja reservés: l’adresse de broadcast (bit adresse mis à 255), ainsi que l’adresse de reseau (bit d’adresse mis à zero). La plage adressable se situe entre ces 2 valeurs.
Adresse mac
Une adresse MAC (Media Access Control), parfois nommée adresse physique,
est un identifiant physique stocké dans une carte réseau ou une
interface réseau similaire. Elle est unique au monde
Une adresse MAC est codée en hexadécimal, sur 6 octets (cf cours sur l’hexadécimal)
00-1E-33-1D-6A-79 est une adresse MAC
=> Ouvrir l’invite de commande windows et entrer la commande ipconfig /all. identifier l’adresse MAC de votre ordinateur.
Projet de fin de chapitre: conception d'un objet simple (arrosage automatique, alarme, feu tricolore) avec algorithme, capteurs et actionneurs identifiés.
Atlas (2013), robot androïde de Boston Dynamics. Wikipedia.
Le terme robot est issu des langues slaves et formé à partir du radical rabot, rabota (работа en russe) qui signifie travail, corvée que l’on retrouve dans le mot Rab (раб), esclave en russe. wiki.
Les robots sont utilisés pour des tâches qu’ils remplissent mieux que les humains. Il peut s’agir d’un travail répétitif, d’une tâche de haute précision, ou d’une activité dans un milieu hostile.
Dans l’antiquité: Le mythe de Pygmalion racontait déjà comment la statue Galatée devint vivante et s’affranchit de son créateur afin de partir à la conquête du monde des hommes.
A la Renaissance, Le premier exemple d’un robot de forme humaine fut donné par Léonard de Vinci en 1495. Ses notes à ce sujet recelaient des croquis montrant un cavalier muni d’une armure qui avait la possibilité de se lever, bouger ses membres.
La litterature de science fiction du XIXe et XXe regorge d’exemples, mettant en scène des robots. Une oeuvre majeure est celle de Isaac Asimov: Les Robots (1950), dans laquelle il énonce les 3 lois de la robotique. Ces trois lois forment un principe d’organisation, qui donne un cadre aux différentes nouvelles.
Les premieres machines autonomes, capables d’interagir avec l’homme apparaissent dans les années 1980.
Computer History Museum, San José, CA
Les robots ne sont pas de simples automates: ils ont la capacité de s’adapter à leur environnement dans leurs déplacements et leurs actions. Ils analysent leur environnement pour réagir par le biais de capteurs et de programmes. Ils peuvent réagir à des situations imprévues (piece defectueuse, obstacle).
Diversité des robots actuels. Wikipedia.
Definition: Un robot est une machine possédant un processeur, une mémoire, des interfaces d’entrée et de sortie, et qui capable d’exécuter des programmes. C’est aussi la définition d’un ordinateur. La différence se situe avec la nature des capteurs et actionneurs que possède le robot, ce qui lui donne une action autonome, en temps réel et remplace souvent une activité humaine.
On distingue parmi les extensions de la machine-robot, celles qui sont commandées (ACTIONNEURS) de celles qui numérisent une grandeur physique (CAPTEURS)
C’est alors un programme, écrit en langage informatique, qui va traiter les données et commander la machine-robot, lui donnant un comportement autonome, en temps réel.
Son comportement peut aussi être commandé par une autre machine, dans un système informatique disttribué.
Description d’un système automatisé
Le système automatisé comprend les sous-parties du robot, les interfaces, les machines utiles pour le traitement, les sources d’énergie.
On peut représenter les sous-parties de ce système informatique avec les chaines d’information et d’énergie.
Chaine d’information et chaine d’énergie
Chaine d'information et chaine d'énergie, structure des systèmes
Chaine d’information
La chaine d’informations permet de transmettre entre différentes parties et traiter les données au niveau d’une machine.
Décrire la chaine d’information revient à placer les verbes ACQUERIR, TRAITER LES DONNEES, COMMUNIQUER dans un diagramme d’activité:
Camera -> ACQUERIR (images) -> TRAITER LES DONNEES (microcontroleur) -> COMMUNIQUER (antenne radio, interface de communication) -> stockage et traitement (serveur)
ou bien :
Camera -> ACQUERIR (images) -> TRAITER LES DONNEES (microcontroleur) -> COMMUNIQUER -> actionneur
Chaine d’énergie
La chaine d’énergie montre l’utilisation des différents capteurs et actionneurs, et la nature du travail (mécanique, électrique, lumineux) qui est mis en jeu.
Décrire la chaine d’information revient à placer les verbes ALIMENTER, DISTRIBUER, CONVERTIR TRANSMETTRE dans un diagramme d’activité:
Les robots et microcontrôleurs doivent souvent avoir une alimentation autonome, qui doit durer le plus longtemps possible. Il faut alors optimiser leur consommation électrique.
Bilan: robot ou objet connecté
La diversité de machines, et leur interaction, montre que le robot fait partie d’une plus grande famille d’objets, dont l’enjeu dépasse aujourd’hui le simple fait d’agir de manière autonome. Ce sont aussi et surtout des objets connectés, en reseau.
On parlera plus d’objets connectés que de robots.
Informatique et internet des objets
Video du mooc SNT sur IOT
A partir de la video: citer un ou des capteurs, actionneurs, un exemple de programme. Qu’est-ce qu’un objet connecté?
Constitution d’un objet connecté
Un objet connecté a une fonction: il est prévu pour réaliser certaines tâches en rapport avec la mission qu’il doit accomplir.
Un objet connecté est muni de:
Capteur: transformation d’une mesure physique en un signal électrique.
Actionneur: transformation d’un signal electrique en un moyen physique
Processeur: pour un traitement local des données, plus ou moins complexe
Source d’énergie: adaptée à la fonction
Moyen de communication: du codage à la transmission des données selon des protocoles standards ou dédiés.
Enfin, l’objet peut disposer également d’une IHM (interface homme-machine), souvent par l’intermédiaire d’une application.
Définition d’un objet connecté
Définitions d’un objet connecté et de l’Internet des Objets (IdO), ou Internet of Things (IOT):
Un objet connecté dispose de tout ou partie des caractéristiques d’un robot, mais surtout, fait partie d’un système informatique à plusieurs machines, reliées au réseau internet.
Les fonctions sont alors reparties sur l’ensemble de ces machines, et il peut arriver que le programme ne soit pas dans l’objet lui-même, mais dans une autre machine du système (le client, le serveur…)
Enfin, grâce à la connexion internet, la communication peut se faire entre appareils eux-mêmes, ou entre appareils et le Cloud.
Les objets connectés sont donc des objets physiques connectés ayant leur propre identité
numérique et capables de communiquer les uns avec les autres.
Un objet connecté a deux rôles principaux:
La collecte de données issues de son univers (surveillance)
Un seuil d’ action: selon les données recueillies et communiquées. Ainsi, par exemple, déclencher l’arrosage du gazon lorsque la chaleur externe est trop élevée.
Retrouver tous les constituants de l’objet connecté à partir de l’un des exemples proposés.
Exemple 3
A quoi servent-ils?
Un objet connecté a une fonction: il est prévu pour réaliser certaines tâches en rapport avec la mission qu’il doit accomplir.
les objets connectés proposent un certain degré de commodité dans notre quotidien. Grâce à cet objet, nous pouvons gagner beaucoup de temps et parfois d’énergie. L’idO est employé dans différents domaines d’activité.
Vous les trouvez partout, de la machine à café aux jouets pour enfants: TOUT est susceptible de se transformer en IOT!
La collecte des données en temps réel offre beaucoup de potentiel:
l’automatisation à partir de ces données
une gestion à distance
un historique qui peut être analysé
Par ailleurs, l’Internet des objets vise à relever différents challenges majeurs actuels et futurs. page eurotechconseil.com:
Les smart-cities: pilotent le flux de circulation ou les illuminations en temps réel en fonction de l’heure de la journée. Une telle avancée technologique permet de régler certains des problèmes de saturation des centres-villes et de la pollution par la lumière, et de réduire les émissions de CO2.
transports publics: plusieurs capteurs existent pour diffuser des informations précieuses ainsi que pour réguler la circulation et renseigner les passagers en temps réel.
Dans les secteurs industriel et agricoles, l’idO augmente la productivité: surveillance des cultures et analyse du sol, arrosage intelligent, suivi distant de cheptel.
Aquaculture: station météo sous-marine avec surveillance de la qualité des eaux, détection de la pollution ou de contamination.
Domotique: thermostat intelligent, électroménager connecté, alarme connectée, pilotage de l’éclairage, des stores…
Santé: paire de lunette connectée pour une personne en situation d’handicap, peut fournir des informations sur les lieux alentour, bracelet connecté pour les personnes sourdes (envoi d’une impulsion selon l’activité ou les messages perçus), mesure du rythme cardiaque
Loisirs: balises GPS de géolocalisation de randonneurs, drones pour filmer
defense: drones de combat
Il peut donc exister autant d’objets connectés qu’il existe d’activités humaines.
Un objet connecté dans le reseau internet
modèle Client-serveur
La communication entre un objet connecté et sa plateforme est du type client-serveur.
Comme toute machine sur internet, un objet est identifié par son adresse IP. Dans son réseau, le canal de communication privilégié sera le Wi-Fi, le Bluetooth, la puce RFID…
Le programme et les données: souvent, le programme n’est pas dans l’objet, mais dans le serveur prévu. L’utilisation du serveur necessite souvent de renseigner des informations personnelles lorsque l’on utilise un service connecté. Cela peut poser un problème sur la protection et l’usage de ces données.
Les IOT sont-ils particulièrement vulnérables?
On a vu que la communication entre Client et Serveur sur internet doit être authentifiée, que les données doivent circuler sans être modifiées (intégrité), et de manière confidentielle. Ce sont les protocoles HTTP(S), IP et TCP qui assurent le transport de cette manière. Le problème est que ces objets connectés disposent de moins d’énergie qu’un ordinateur, et d’une faible bande passante. Ces protocoles sont donc adaptés pour les IOT, mais avec moins de sécurité.
Les IOT sont vulnérables, les failles de sécurité concernent:
la force des mots de passe employés pour se connecter à l’objet, voire l’absence de mots de passe (bluetooth, wifi direct): authentification pas assez securisée.
le wifi vulnérable, ce qui permet
de couper l’accès au réseau pour l’IOT (probleme s’il s’agit d’une caméra de surveillance)
de s’introduire dans le réseau, d’intercepter les données
l’IOT peut conserver le nom des utilisateurs. Recueillir ces noms d’utilisateurs peut être utilisé pour un attaque par phishing
l’absence de mise à jour du logiciel de l’IOT. Des failles de vulnérabilité permettent à un pirate de découvrir des ports ouverts et de prendre le contrôle de l’objet.
La sécurité de la plateforme, du logiciel côté serveur avec sa base de données peut poser des problèmes de confidentialité des données.
Quels sont les moyens de sécuriser les IOT ?
Des normes de sécurité rigoureuses préconisent:
l’authentification et les autorisation doivent être robustes
le chiffrement des données entre l’IOT et la plateforme
garantir l’intégrité des données (verification avec une fonction de hachage par exemple)
des mises à jours régulières des logiciels, avec des correctifs réguliers de la part du constructeur
une surveillance en temps réel pour détecter toute activité suspecte
Problème de confidentialité des données
De manière générale, les objets connectés font peser des risques en matière de vie privée avec la collecte des données. La Chine a ainsi développé un système de crédit social basé sur une surveillance généralisée de sa population (caméra et capteurs). Leur comportement est noté et les incivilités sont punies par l’abaissement de la note sociale des individus. Ceux-ci ne peuvent plus par exemple acheter un billet de train s’ils ont commis une incivilité dans les transports.
Variété des modes de communication
La plupart des IOT sont connectés sur internet via la wifi.
Certains objets, comme les cartes à puce ont une architecture et un moyen de communication différents. Ce sont des cartes en plastique d’au moins 1mm d’epaisseur.
image issue de wikipedia
La carte à puce contient un circuit intégré avec, selon le modèle:
de la mémoire flash
de la mémoire non volatile
un microprocesseur (pour les cartes à microcontrôleur)
Elles sont souvent utilisées comme moyen d’identification.
RFID: Radio Frequency Identification: c’est une méthode permettant de mémoriser et récupérer des données à distance. Le système est activé par un transfert d’énergie électromagnétique entre une étiquette radio et un émetteur RFID. L’étiquette radio composée d’une puce électronique et d’une antenne reçoit le signal radio émis par le lecteur lui aussi équipé d’une technologie RFID. Les composants permettent à la fois de lire et de répondre aux signaux.
fonctionnement du RFID
L’antenne reçoit un signal électrique alternatif, émis à distance par le terminal. La puce convertit ce signal en tension continue (alimente la puce) et alternatif (horloge pour synchroniser les echanges).
On trouve cette technologie dans les puces pour animaux, clés de voiture, badges d’entrée, badge pour transport en commun… voir article sur RFID et NFC
Le programme et les données: souvent, le programme n’est pas dans l’objet, mais dans le serveur prévu. L’utilisation du serveur necessite souvent de renseigner des informations personnelles lorsque l’on utilise un service connecté. Cela peut poser un problème sur la protection et l’usage de ces données.
Une obsolescence programmée
la durée de vie de ces objets peut être écourtée indépendamment de l’usure physique de l’objet. En effet, le fonctionnement des objets connectés dépend aussi de services proposés par le fabriquant, qui peut cesser avec son activité. Ce fut le cas du lapin connecté Nabaztag lancé en 2005, qui a cessé en 2011 avec l’arrêt des serveurs de la société.
Le robot supérieur aux humains?
Ces videos virales sur Youtube. Vrai ou Faux Robot?
Exemple avec cette vidéo montrant un robot qui fait un superbe point contre le Polonais Pavel Sirucek
les vidéos de robotique virales nous conduisent à la prudence et à une analyse plus critique de ce que nous voyons.
CNIL: il-etait-une-fois-lours-connecte-mal-securise Le piratage massif d’un ours en peluche connecté a entrainé la fuite sur internet des informations personelles de plus de 800 000 familles. (suivi de demandes de rançons)
Sojourner (de la sonde Mars Pathfinder est le premier rover géologue envoyé sur Mars. Il a ouvert la voie aux autres Spirit, Opportunity (2003), Curiosity (2011), Perseverence (2021) et Zuhrong (2021).
le robot explorateur Pathfinder (1997) en plein travail
Ce premier rover, muni d’un moteur (chenilles), d’une batterie solaire et une autre au Lithium, disposait d’une camera, une station meteo, et d’un spectromètre à RX pour analyser les échantillons minéraux. Il possedait egalement une antenne, dirigée vers la Terre pour ses communications.
Les programmes qui le contrôlaient devaient lui permettre d’evoluer de manière plus ou moins autonome sur la surface de Mars, et de réaliser diverses mesures physiques, tout en veillant à sa propre sécurité et autonomie (batteries).
Que fait un programme informatique?
Ce qui fait fonctionner un appareil numérique, c’est un programme:
C’est donc grâce à un programme que l’on fait fonctionner un ordinateur, une console de jeux, une machine à laver, le poste de pilotage d’un avion, un guichet automatique bancaire…
des machines utilisant un programme informatique
Mais c’est aussi grâce à un programme que ces machines peuvent fournir un service: un logiciel de bureautique, un jeu, le lavage du linge, le pilotage automatique, ou le retrait d’argent de son compte….
Aujourd’hui, le smartphone est l’objet qui nous permet d’executer de nombreux programmes, en permanence.
applications et smartphone
On confond parfois programme informatique et logiciel, ou application.
Un logiciel peut comporter plusieurs programmes.
Quelques repères historiques
En 1842, la comtesse Ada Lovelace crée des diagrammes pour la machine analytique de Charles Babbage. Ces diagrammes sont considérés aujourd’hui comme étant les premiers programmes informatiques au monde
1936: Première formulation de ce qu’est un programme par Alan Turing.
1940: Les premiers ordinateurs. Les programmes informatiques étaient alors conçus par des analystes, rédigés par des programmeurs et saisis par des opératrices sur des bandes type cartes en carton perforé.
Le premier système d’exploitation a été développé en 1954.
1970: début de la programmation structurée. Depuis, la variété et mise à jour des langages n’a cessé de rendre plus accéssible la programmation.
Compléter la frise
Algorithme
Un algorithme traduit le cahier des charges d’un programme en un langage naturel et non ambigü, où les instructions sont séquencées.
Quelques exemples
Origami
Cahier des charges:Réaliser une grue (l’animal) par 10 pliages succéssifs d’une feuille de papier.
Algorithme:
extrait de la séquence de pliage
L’algorithme du pliage de l’origami présente une structure linéaire. On peut visualiser celui-ci à l’aide d’un algorigramme
Code PIN
Cahier des charges:Demander à l’utilisateur du smartphone de saisir son code PIN, et s’il echoue 3 fois, lui demander son code PUK
Algorithme: L’un des deux algorithmes correspond bien au cahier des charges
Ce premier algorithme montre une structure alternative: on commence par tester la condition ; si elle est vraie, l’action 2 est exécutée, sinon, c’est l’action 3.
on utilise une variable appelée nbessai. Sa valeur est d’abord mise à 1, puis évolue au fur et à mesure que le programme avance.
on utilise une structure qui amène une répétition. (une structure itérative): Tant que <condition> …qui répète le bloc tant que la condition est VRAIE.
Questions:
Pour l’algorithme 1, compléter l’algorigramme.
Trouver lequel des 2 algorithmes correspond bien au cahier des charges.
Pour les 2 algorithmes: Expliquer ce que fait le programme si l’utilisateur entre 2 fois un code PIN erroné, puis entre le bon (au 3e essai).
Pour l’algorithme 2: expliquer ce que fait le programme lorsque l’on entre 3 code PIN erronés.
Les ingrédients d’un algorithme
Les instructions relatives aux ingrédients d’un algorithme seront données en langage naturel, mais à la manière du langage Python.
Données: Variables et opérations
Une variable stocke une valeur et peut être utilisée pour des opérations.
Les structures répétitives permettent d’exécuter plusieurs fois un bloc d’opérations, tant qu’une condition (de continuation) est satisfaite.
Tantque(<condition>)faire<bloc_opérations>
Structure: Fonctions et Procedures
Les fonctions permettent de rendre le script plus efficace, plus facile à lire et à vérifier. Un bonne pratique est de faire régulierement du remaniement de son code : C’est à dire ré-écrire les parties du programme qui fonctionnent et les mettre dans une fonction. Cela evite aussi les répétitions. On remplace alors le code par un appel à une fonction.
La programmation se fait en deux temps: On commence par programmer la fonction
fonctioncarre(x)y=x*xreturny
Puis on appelle cette fonction:
a=10carre(10)
Le programme retourne dans ce cas la valeur 100.
Langages informatiques
Les instructions qu’un ordinateur devra exécuter doivent pouvoir être exprimées de manière précise et non ambiguë.
Définitions
Un programme informatique
C’est un ensemble d’opérations destinées à être exécutées par un ordinateur.
Un programme source est un code écrit par un informaticien dans un langage de programmation. Il peut être compilé vers une forme binaire ou directement interprété. Au final, les instructions seront traduites en binaire, afin qu’elles soient exécutées par un microprocesseur.
Un langage de programmation
C’est une notation utilisée pour exprimer des algorithmes et écrire des programmes.
Un algorithme
Un algorithme est un procédé pour obtenir un résultat par une succession de calculs, décrits sous forme de termes simples dans une langue naturelle.
C’est une suite finie et non ambigüe d’instructions, permettant de resoudre certains problèmes.
Un bug
Un bug est un défaut de construction dans un programme. Les instructions que l’appareil informatique exécute ne correspondent pas à ce qui est attendu, ce qui provoque des dysfonctionnements et des pannes.
Exercices
Ex 1: code PIN et code PUK
Le programme suivant, est-il celui utilisé pour le deverouillage d’un smartphone? Pour repondre à la question:
dessiner l’algorigramme correspondant.
Expliquer ce que fait le programme lorsque l’utilisateur se trompe 3 fois de suite de code PIN, puis parvient enfin à rentrer le bon (au 4e essai).
Cahier des charges:Une application de course à pieds sur spartphone propose à l’utilisateur de rentrer les distances parcourues chaque jour. Lorsque l’utilisateur a atteint son objectif, fixé à 42 km, le décompte s’arrête. L’ecran affiche alors: Félicitations
Algorithme:
total=0Tantquetotal...:distance=entrer("Saisir la distance : "))...Afficher("Félicitations")
Remarque: l’instruction distance = entrer("Saisir la distance : ")) va afficher Saisir la distance :, puis stocker celle-ci dans la variable distance.
Compléter l’algorithme.
Expliquer ce que fait le programme lorsque l’utilisateur entre successivement: 10, 12, 10, 15.
Ex 3: Diamètre d’ouverture de l’appareil photographique
Cahier des charges:Pour l’appareil photo numérique: Mesurer le flux lumineux. Si celui-ci est supérieur à 100 Lux, diminuer le diamètre d’ouverture. S’il est infèrieur ou égal à 100 Lux, ouvrir davantage.
Remarque: on peut utiliser les fonctions diminuer et augmenter pour agir sur l’ouverture de l’appareil photo.
Exercices supplementaires
Ex 1
On donne le script d’un programme en langage naturel, ainsi que sa traduction en Python. Déterminer, à la fin du programme, les valeurs stockées dans les variables a, b et c.
Programme 1 en langage naturel
a=10b=5c=1si(a==b)c=2*csinona=a+1b=bdiv2
Programme 1 en langage Python
a=10b=5c=1if(a==b):c=2*celse:a=a+1b=b/2
Ex 2
On donne le script d’un programme en langage naturel, ainsi que sa traduction en Python. Déterminer, à la fin du programme, la valeur stockée dans la variable a.
Programme 2 en langage naturel
a=10Tantque(adifferentde0)faireafficher(2*a)a=a-1
Programme 2 en langage Python
a=10while(a!=0):print2*aa=a-1
Ex 3
On donne le script d’un programme en langage naturel, ainsi que sa traduction en Python. Déterminer, à la fin du programme, la valeur stockée dans la variable a.
Programme 3 en langage naturel
pouride1anfairea=3*iAfficher(a)
Programme 3 en langage Python
foriinrange(1,n+1):a=3*iprinta
range(a,b) permet de parcourir les valeurs a, a+1, …, b-1 (b non compris)
Exercices issus du site Algorea
Boucle simple
Plots
Ecrire un programme utilisant une boucle for, permettant au robot de deposer un plot sur chaque repère.
Compléter le programme suivant pour qu’il permette au robot de déposer tous les plots sur les repères. Le programme doit fonctionner quel que soit le terrain (1, 2, ou 3) proposé:
Programmer le robot pour qu’il ramasse sa bille et la pose sur le trou le plus éloigné. Cette fois, on n’utilisera pas le mot-clé for car on ne connait pas à l’avance le nombre de cases à parcourir.
On utilisera plutôt le mot-clé while suivi de la condition à réaliser pour executer les instructions.
Ce sujet contient deux tests, avec une position différente pour le trou. Votre programme doit fonctionner pour les deux.
Pour la première situation, le robot consomme 1 segment de sa batterie chaque fois qu’il pose un plot. Il doit s’arrêter de travailler lorsque sa batterie ne contient plus qu’un seul segment. Comment peut-il tenir le compte du nombre de segments utilisés, et donc, du niveau de sa batterie?
modelisation Coder une image numerique avec un langage de programmation ou dans un fichier de données: Lien
modelisation metadonnées EXIF, programme python pour interagir avec les metadonnées: Lien
Astrophotographie avec un smartphone?
culture numer
Jupyter au smartphone
En disposant un smartphone sur un téléscope, on approche rapidement les limites de la qualité de l’appareil photo: sa capacité à capter les détails: les contours, les petits objets, le manque de contraste et de lumière.
On peut deviner que ce qui caractérise une image numérique, c’est:
sa définition
sa profondeur de couleurs
son poids (en Mo)
Ces caractéristiques vont dépendre de la chaine d’acquisition de l’image, dont l’appareil photographique fait partie.
L’appareil photographique numérique
Présentation
Video: Fonctionnement d un appareil photo numérique
Composants principaux
On retrouve dans un appareil photographique numérique, ou pour la partie photographie d’un smartphone ou d’une tablette, les constituants suivant :
L’objectif photographique : c’est un système optique, amovible ou non, convergent et composé généralement de plusieurs lentilles.
objectif d appareil photo
objectif photographique smartphone
La cellule d’exposition : c’est un composant électronique qui permet de mesurer la lumière renvoyée par le sujet et de régler l’ouverture du diaphragme, le temps d’ouverture de l’obturateur, et le déclenchement du flash. Cela permettra d’obtenir une exposition correcte.
L’obturateur est une piece qui s’ouvre et se ferme pour laisser passer la lumiere pendant un temps appelé temps d’obturation, choisi par le logiciel.
Le diaphragme : c’est une piece dont le diamètre (l’ouverture) est réglable. Ceci permet de limiter la quantité de lumière qui rentre dans l’appareil photographique.
un filtre de Bayer (RVB), sans qui la photo serait en N&B
filtre de bayer et photosite
Ce filtre de bayer est en réalité constitué de 3 filtres. La lumière issue de l’objectif traverse la grille de filtres colorés avant d’éclairer la grille de photosites.
un capteur, constitué de photosites, répartis sur une grille. Ce capteur se trouve à l’endroit où la lumière est focalisée (nette). Les photosites transforment l’intensité lumineuse en signal électrique.
Cette grille de photosites correspond à la pellicule photosensible des appareils photo argentiques. Sauf qu’avec un appareil photo numérique, l’image est construite en données …numériques, qui correspondent aux pixels.
Sur l’image suivante, on voit que la grille contient des carrés constitués de 2 cellules sensibles au vert, 1 cellule au bleu et 1 cellule au rouge. Il y a donc 2 fois plus de cellules vertes que de cellules rouge ou bleu.
plan de photosites
Une carte mémoire (SDcard), pour y enregistrer les images.
un ordinateur interne capable de traiter des programmes.
Le plus petit détail d’une image: le PIXEL
L’image est construite en données numériques qui correspondent aux pixels.
C’est le grain de coloration d’une image, l’atome de l’image numérique.
La Definition d’une image correspond au nombre de pixels de l’image, exprimé en largeur * hauteur (par exemple 800 * 600).
Codage
Pour une image en noir et blanc: le codage numerique sera de 1 bit par pixel.
Pour une image couleur: Un des algorithmes possibles consiste à créer un pixel à partir de 4 photosites : un bleu, un rouge et deux verts. Un pixel sera alors composé de 3 couleurs : rouge, vert, bleu (RVB).
Restitution
Sur un écran numérique, un pixel est constitué de 3 diodes luminescentes, presque au contact, et qui vont restituer la couleur en un point. Ces 3 diodes constituent le pixel.
Lorsque l’on agrandit l’image, celle-ci parrait nette si la définition de l’image numérique est supérieure à celle de l’écran.
detail des pixels d'un iphone
De manière générale, c’est la densité de pixels qui va donner le détail de l’image. Elle est exprimée en pixels/cm ou pixels/pouces. C’est la résolution d’un écran.
faible/forte densité de pixels, image de formettic.be
Les réglages de l’appareil photographique se font la plupart du temps de manière automatique.
Mise au point: La mise au point est l’opération qui consiste, pour un photographe, à régler la netteté de l’image qu’il veut obtenir.
Algorithmes de prise de vue
l’appareil photographique est capable de mesurer la quantité de lumière, et de régler seul:
le diapragme : c’est la taille de cette ouverture qui détermine la quantité de lumière arrivant sur le capteur.
la vitesse d’obturation : correspond à l’intervalle de temps durant laquelle l’obturateur de l’appareil photo laisse entrer la lumière. Plus cette vitesse est lente et plus l’appareil photo capte la lumière. L’ image sera alors plus lumineuse. Ce réglage influe aussi sur la profondeur de champs, et la netteté des images pour des sujets en mouvement (mode sport).
Algorithme d’aide à la mise au point
Parfois, la mise au point automatique n’est pas possible. Certains appareils photographiques proposent une option d’aide appelée le Focus Peaking (l’intensification de la mise au point). C’est utile lorsque le sujet manque de lumière, ou que l’on utilise un objectif manuel.
En rouge, le focus peaking qui indique la zone de mise au point
Voici un exemple d’algorithme utilisé:
pour chaque pixel:
si le contraste avec un pixel voisin est fort alors:
colorier le pixel en rouge
Algorithmes de correction
Correction du flou: Une image floue est une image dont la valeur radiométrique de chaque pixel a été altérée localement par les valeurs des pixels au voisinage. Ce problème est du au temps d’exposition qui est trop long.
Les algorithmes de correction de flou on beaucoup progressé avec la cartographie mobile. En effet, il n’était pas possible de ralentir le vehicule lors des prises de vues (circulation routière de jour), ni d’utiliser de flash puissant pour éclairer les façades (nuit).
véhicules terrestres decartographie mobile
L’algorithme utilisé va alors calculer le mouvement des pixels pour reconstruire l’image nette.
résultat du traitement par algorithme
algorithme de correction des couleurs L’intensité de la couleur est mesurée par la saturation. Les applications de traitement d’image permettent la correction de la saturation grâce à des filtres, qui seront appliqués à tous les pixels de l’image.
Qu’est ce qu’une photographie numérique ?
Une photographie numérique, comme tout autre objet numérique, c’est un fichier de données numériques, c’est à dire des valeurs codées en binaire.
Une partie des données correspond à des métadonnées, c’est à dire des données périphériques. L’autre partie contient les données relatives à l’image: pour chaque pixel, le fichier contient les données des intensités RVB.
Données EXIF pour plus de détails sur les métadonnées.
Enjeux ethiques et societaux de l'image
L’intégration des appareils photo dans les smartphones a multiplié les usages d’une photographie:
La photographie n’est plus seulement utilisée pour conserver les souvenirs mais permet à tout instant de partager un moment ou de servir d’aide-mémoire.
Cela engendre des problèmes de stockage mais également de droits. En effet, à l’heure où des millions de photos sont mises en ligne sur les réseaux sociaux, des espaces communautaires comme Flickr, Instagram et où la duplication est instantanée, la protection des données et le respect des droits d’auteur représentent un enjeu majeur.
Le support de l’image comme témoignage ou éléments de preuve est remise en cause en raison de la facilité avec laquelle on peut effectuer des retouches sans qu’on les détecte.
culture numer
Droit à l’image des personnes photographiées
Contexte
“Ni l’auteur, ni le propriétaire d’un portrait, ni tout autre possesseur ou détenteur d’un portrait n’a le droit de le reproduire ou de le communiquer au public sans l’assentiment de la personne représentée ou celui de ses ayants droit pendant vingt ans à partir de son décès”.
Selon ce principe, l’autorisation de la personne photographiée doit être demandée.
Le droit à l’image ne s’applique pas à une personne photographiée de dos ou dans une foule.
Personnalité publique
Cependant, pour les personnages publics et les personnes privées qui accèdent temporairement à la vie publique, cette autorisation est considérée comme implicite, pour autant que les images relatives à la vie publique des personnes concernées soient publiées dans un contexte de couverture d’événements relevant de l’actualité. Ces photos ne peuvent en aucun cas être dénigrantes ou diffamatoires et elles doivent avoir un rapport avec la fonction ou le métier exercé par la personne photographiée.
Diffamation
En tout état de cause, le respect de la vie intime et de la dignité de la personne humaine primera toujours sur la liberté d’expression.
Droit d’auteur
Propriété intellectuelle
Une œuvre est protégée automatiquement, du simple fait de sa création et sans qu’il soit nécessaire de procéder à aucun enregistrement, dépôt, paiement de taxe, ou autre formalité.
Toutes les productions du domaine littéraire, scientifique et artistique, quel qu’en soit le mode ou la forme d’expression, telles que notamment les livres, brochures et autres écrits, les conférences, les compositions musicales avec ou sans paroles, les œuvres chorégraphiques, dramatiques, audiovisuelles, multimedia, les dessins, peintures, sculptures, les plans d’architecte, les photos, les œuvres de l’art appliqué, les bases de données, les programmes d’ordinateur, sites internet… exprimées dans une forme originale.
Pour être protégée, l’œuvre doit donc :
être originale
Cette condition n’est pas formellement définie par la loi. On considère généralement qu’une œuvre est originale lorsqu’elle représente l’expression de l’effort intellectuel de l’auteur qui l’a réalisée et/ou lorsqu’elle porte l’empreinte personnelle de celui-ci.
être mise en forme
La création doit avoir atteint une certaine « concrétisation », sans nécessairement que l’œuvre soit achevée. Les idées, les concepts ne sont pas protégeables.
Reproduction d’une oeuvre
Les œuvres exposées sur la voie publique ne font pas partie du domaine public. S’il s’agit d’une œuvre originale protégée par le droit d’auteur, imaginons des sculptures de Folon exposées au parc royal, l’autorisation de l’auteur sera toujours nécessaire pour publier des photos des œuvres exposées.
images sur le Net
Très souvent, les images disponibles sur internet, qu’il s’agisse de photos ou d’images graphiques, ne sont pas libres d’utilisation.
En aucun cas, le fait qu’une photo soit disponible dans une banque d’image ne signifie que la personne représentée a donné son accord à la reproduction ou la communication au public de son image ! Une autorisation expresse est toujours nécessaire.
Il en va de même pour les logos, dessins, images graphiques disponibles dans ces banques d’image. Non seulement, le nom de l’auteur est rarement mentionné, mais, généralement, il n’a pas donné son accord pour la diffusion et l’utilisation de ses créations.
En reprenant des photos ou des images protégées par le droit d’auteur, vous vous rendez coupable d’un acte de contrefaçon puni civilement et pénalement. La plus grande prudence s’impose donc.
Licence Creative Commons
Détourner d’images
Une pratique virale
L’image numérique peut être facilement modifiée, transformée, et devenir un objet complètement artificiel.
la nécessité d’illustrer un contenu sur le web est devenu tellement indispensable qu’il est préférable d’utiliser une image «passe-partout» voire inappropriée plutôt que rien du tout!
*Une seule image, et des milliers d’interprétations possibles.*
L'article suivant
une image source, impersonnelle
Quelques exemples
Des images numériques crées par superposition de calques.
Source : okeit.net
Source : awkward.com
Cette « vague de riz » est une sculpture japonaise exposée dans un magasin d’alimentation à Tokyo.
Vérifier l’authenticité d’une image ou d’une information numérique
Une photo ou une vidéo n’est jamais une preuve en soi. Pour vérifier la nature d’une photo, on peut effectuer une recherche sur Google photo, non pas par mots-clés, mais par images (uploader ou coller l’URL). On peut aussi faire un clic droit sur l’image et choisir (Google lens).
TP données EXIF et données colorimetriques
Partie 1 : synthèse additive des couleurs
Pour une image en couleur: À chaque pixel on associe 3 couleurs, le rouge, le vert et le bleu. On parle du canal rouge, du canal vert et du canal bleu d’un pixel (système RVB ou RGB en anglais).
La valeur de l’intensité lumineuse associée à chaque canal de chaque pixel d’une image est comprise entre 0 et 255 (256 valeurs possibles). On codera donc un pixel à l’aide d’un triplet de valeur (par exemple (247,56,98) en code décimal, ou son équivalent en hexadecimal : (f7,38,62)
Ouvrir le lien suivant :
www.proftnj.com/RGB3.htm
Question a: à l’aide du logiciel :
Quelle est la couleur donnée par ce triplet de valeurs ? (247,56,98)
Question b: Combien de couleurs différentes est-il possible d’obtenir avec ce système RVB ? (combinaison de 3 couleurs, codées chacune sur 256 valeurs,…)
Question c: Pour chacune des couleurs du tableau, indiquer le code couleur RGB décimal correspondant:
Certaines informations, contenues dans le fichier image, donnent des informations sur les conditions de la prise de vue, le type d’appareil utilisé, la géolocalisation, les dimensions de l’image… Ces données suivent un format précis du standard EXIF.
Utilisez un logiciel en ligne de lecture des données EXIF, comme par exemple :
onlineexifviewer.com/
Télécharger l’image suivante sur votre disque dur
Select image depuis le logiciel en ligne
cliquer sur l'image pour telecharger
Le logiciel met ces données EXIF sous une forme lisible par un être humain :
Question d compléter les informations contenues dans le fichier de cette photographie :
information
donnée EXIF
L’appareil photo utilisé
La lentille de l’objectif
Les coordonnées GPS du lieu où la photo a été prise
La date de la prise de vue
Le nombre de pixels
Poids de la photo en ko Mo
Question e: Quel est l’endroit où la photo a été prise (pays, region, commune) : utiliser le lien proposé vers openstreetmap par exemple.
Partie 3: Vrai ou Fausse photo?
Le paragraphe suivant explique qu’il est possible de faire une recherche par image, et, peut-être, de retrouver la source.
Question f: L’image suivante est-elle une vraie image?
TP pixel art
Pixel art
Codage d’une image numérique
Une image numérique est constituée de pixels juxtaposés dont on règle l’intensité lumineuse.
L’image suivante montre le caractère a obtenu en remplissant judicieusement la grille de pixels de 5 pixels * 6 pixels.
C’est en prenant un recul suffisant que l’image retrouve sa finesse, et que les pixels se mélangent pour former la lettre a.
Ici, l’image est en noir et blanc. Les pixels ont une intensité que l’on pourrait représenter par 0 ou 1.
Les pixels d’intensité lumineuse égale à 0 sont noirs. Ceux à 1 sont blancs.
détails du caractère a
On pourrait représenter chaque ligne de cette image par une liste de valeurs 0 ou 1 :
ligne1 = [1, 0, 0, 0, 1]
L’image entière serait alors une liste de listes (une liste contenant les listes de chaque ligne).
On donne ci-contre un extrait :
à vous de jouer: Compléter la liste contenant l’image du bateau.
L’écran LED de la carte microbit
La carte microbit est un microcontrôleur que l’on peut programmer en Python. Cette carte dispose de capteurs intégrés (temperature, luminosité, champ magnétique), peut communiquer par ondes radio.
Et surtout, elle dispose d’un écran de diodes électroluminescentes (DEL), que l’on peut allumer en fonctions des coordonnées x, y de ces diodes.
coordonnée pour chacune des DEL x,y
La grille de DEL de la carte microbit est constituée d’un plan de 5 * 5 LED.
L’intensité lumineuse est ajustable avec une valeur entre 0 à 9.
La valeur 0 correspondant à la LED éteinte, 9, allumée au maximum.
Il y a donc 10 niveaux d’éclairement, pour chaque pixel.
# instruction pour allumer une DEL en x,y
display.set_pixel(x,y, 9)
# instruction pour éteindre une DEL en x,y
display.set_pixel(x,y, 0)
Le simulateur de carte microbit
Programmer l’affichage d’une image
Imaginons que nous ayons à créer une structure de données qui contienne l’image d’un bateau.
deux mâts dessiné avec un tableau de DEL 5 x 5
On propose le programme suivant en langage Python:
Pour lancer le simulateur, appuyer sur le bouton
Pour revenir au script, appuyer à nouveau sur
Le programme de la carte microbit contient en général une boucle qui est répétée indéfiniment: while True à la ligne 12.
Dans le bloc qui est répété:
la boucle bornée for à la ligne 12 créé une variable j, qui prend successivement les valeurs 0, 1, 2, 3 et 4. Ces valeurs correspondent aux coordonnées x des DEL à allumer.
à la ligne 13: la structure conditionnnelle if teste si l’élément de la liste x = j et y = 0 est égal à 1:
s’il est égal à 1: on allume la DEL en (x,y) = (j,0)
sinon, on laisse éteint
Ce programme ne sert donc qu’à allumer les DEL de la première ligne, celle de rang 0.
Afficher l’image entière
Pour afficher l’image entière, il faudra aussi parcourir les lignes 1, 2, 3 et 4 de la liste.
On pourrait adapter le script en ajoutant dans le bloc while True:
à vous de jouer: compléter le script précédent, directement dans la fenêtre d’édition, afin d’afficher l’image entière.
Amélioration du script
Comme vous l’imaginez, il sera possible d’eviter toutes ces répétitions grâce à l’ajout d’une nouvelle boucle for. La structure devrait ressembler à ceci:
modelisation Analyse d’une trame NMEA en langage python: Lien
App utilisant la geolocalisation sur smartphone
culture numer
Sur Iphone: Réglages > Confidentialité > Services de localisation.
On peut paramétrer les permissions pour chacune des app de son smartphone.
Lorsque l’on choisit une app, celle-ci précise à quoi serviront les données de localisation (celles de la
trame NMEA
Booking, Expedia: “pour trouver des hébergements et hôtels près de chez vous”
Facebook, Instagram: “pour aider à indiquer votre présence dans un lieu, pour être notifié des évènements locaux, pour personnaliser du contenu”
météo: “quand des épisodes de pluie ou de neige commencent”
…
Par défaut, de nombreuses applications sont susceptibles de traquer vos données de géolocalisation, afin d’étbalir au mieux votre profil. Voir la video ci-dessous: Un espion dans ma poche?
Envoyé special, Francetvinfo.fr
Voici un exemple de la promesse faite à l’utilisateur: l’incrustation des recommandations en réalité augmentée…
realité augmentée. fiction ou réalité?
Les cartes numériques
Les services de cartographie numérique, comme geoportail ou openstreetmap mettent à disposition des images géoréférencées, avec plusieurs profondeur de zoom disponibles. A ces cartes sont ajoutés des repères avec des lieux d’intérêt.
Comment gère t-on la profondeur de zoom? Pour une même zone géographique, le service stocke des tuiles: ce sont les images assemblées, géoréférencées autour du point central, proposées à certaines échelles. Seules certaines échelles sont disponibles:
*Les pyramides des caches d’images du Géoportail pour le WMTS comportent 21 niveaux de zoom.*
d’un fond de carte constitué avec des tuiles: il s’agit d’images figurant un fragments de la carte, qui, rassemblées à la façon d’un puzzle, forment le fond de carte.
des calques, qui ajoutent certaines informations pour enrichir la carte (altimétrie, cadastre,…). Ils ont une transparence.
de POI: points of interest
d’un repère de coordonnées, dont la norme est Dgrés décimaux (DD).
Les calques servent à regrouper des objets, par ordre d’empilement.
détails sur geoservices.ign.fr
Dans ce dernier exemple, chaque tuile est une image matricielle: elle peut être agrandie mais sans détails supplémentaires jusqu’au chargement d’une nouvelle tuile.
Alors que les quadrillages sont toujours aussi nets: ce sont des images vectorielles ajoutées.
Les cartes de
Géoportail
Elles permettent de zoomer, et ainsi de modifier dynamiquement l’echelle, mais aussi de mesurer une surface, créer un itinéraire, …
voir ici
Openstreetmap
Les fichiers d’itinéraires sont un autre exemple de données standardisées afin de pouvoir être échangées entre applis de cartes numériques: c’est le format .GPX
L’ensemble des itinéraires peut être représenté à l’aide d’un graphe pondéré. Les noeuds sont des intersections, souvent des villes, croisements, points d’interêt. Les arêtes sont les routes.
Le calcul d’itinéraire se fait à l’aide d’algorithmes prenant de nombreux paramétres en compte. L’itinéraire est alors une liste de coordonnées de noeuds dans ce graphe.
Quel itineraire est retourné par l’appel de la fonction avec les paramètres suivants: recherche_itineraire("Montpellier", "Lyon", graphe) ?
Montpellier => Lyon
2. Quel autre itineraire est retourné par l’appel de la fonction avec les paramètres suivants: recherche_itineraire("Lyon", "Montpellier", graphe) ?
Lyon => Montpellier
3. Cet algorithme donne t-il à coup sûr le chemin le plus court? Pourquoi?
L’algorithme de Dijkstra
On a vu que l’algorithme précédent n’est pas efficace pour trouver le meilleur itineraire. Celui-ci n’assure pas non plus de trouver un itinéraire, car il n’y a pas de retour en arrière possible.
L’idée de cet algorithme est de procéder comme pour un parcours de graphe en largeur. On tient à jour une liste de sommets adjacents, qu’il faudra visiter dans l’ordre. Pour un noeud N visité dans la liste, on ajoute les sommets adjacents à N en fin de liste. Puis on progresse dans la liste.
Mais ici:
Le graphe est pondéré (les arêtes ont un poids qui correspond à la distance)
La liste contient pour chaque sommet visité: le noeud et sa distance cumulée au sommet de départ.
la liste des sommets à visiter est remise à jour, triée par ordre croissant de distance cumulée.
Une présentation en vidéo de cet algorithme:
video - Lelivrescolaire.fr
Documents et liens
Livre Delagrave, activité 5 page 89
Cartographie numérique pour débutant: blog
Prérequis: La lumière, transport d’une information par modulation cours de PC 2nde
Traquer un telephone portable
Dans la série Person Of Interest, le personnage principal, Finch, utilise une entité numérique, la machine pour effectuer une surveillance globale de la population, qu’il a lui même mise en place pour les États-Unis. La série soulève de nombreuses questions quant au respect de la vie privée.
voir extrait du film S2E3 13'
Questions:
Cet extrait, vous parait-il réaliste?
Dans ce passage du film, quel dispositif détermine la position de Sophia? (le film evoque une antenne, mais c’est plus probablement le mobile de Sophia)
Quel dispositif partage cette position?
Mesurer le temps pour determiner une distance
Les systèmes américains GPS et européens Galiléo permettent la géolocalisation par satellite d’un recepteur.
La géolocalisation est le calcul de la position sur Terre.
Le récepteur va recevoir en continu 2 types d’informations de la part de chacun des satellites:
la position du satellite
l’heure d’envoi du signal depuis le satellite t0
Le recepteur va utiliser ces informations pour réaliser un calcul de positionnement. D’abord en calculant sa distance au satellite: Il utilise les temps t0 d’emission du signal et t1, celui de reception:
Le signal se deplaçant à la vitesse de la lumière, c = 300 000 km/s.
Cette durée, t1 - t0 est calculée à partir des temps t1 et t0, mesurés par deux horloges différentes, et qu’il faudra synchroniser au mieux.
Exercice: Calculer la distance satellite-recepteur si le temps de transit t1-t0 est egal à 70ms.
L’horloge du récepteur nécessite d’être régulièrement synchronisée avec celle des satellites émetteurs. C’est grâce à un algorithme calculant sur les écarts de positionnement, que l’horloge du récepteur se met à l’heure des émetteurs. Cela nécessite de capter les signaux d’au moins 4 satellites GPS.
Principe de la trilatération
1964 : Le premier système de positionnement par satellites est développé par les États-Unis, à usage uniquement militaire
1995 : ouverture mondiale au reseau GPS, le Global Positioning System
GNSS est l’appellation du groupement de systèmes de positionnements par satellites qui envoie des données de localisation et d’horaire depuis leur orbite. Le système GNSS comprend le célèbre système de positionnement GPS (Global Positioning System), le système de positionnement russe GLONASS, le système de positionnement chinois BeiDou mais aussi le nouveau système de positionnement européen Galileo.
En équipant chaque satellite d’un émetteur radio, il est possible de réceptionner les signaux provenant d’appareils reconnus et d’estimer les délais de synchronisation.
Orbites de la constellation de satellites du système GPS - wikipedia
Pour déterminer la position précise du recepteur sur Terre, il faut utiliser le resultat du calcul de la distance à 4 satellites, et déterminer le point d’intersection de 4 sphères (video explicative).
KEZAKO: Comment fonctionne un GPS?
Pour optimiser le système, les satellites de navigation circulent sur une orbite moyenne à une altitude d’environ 20000 kilomètres. Compte tenu de cette donnée et de la nécessité que le récepteur puisse en permanence avoir quatre satellites visibles au-dessus de l’horizon, un système de navigation (GPS, Galileo, Beidou, Glonass) doit comporter environ 25 satellites de navigation opérationnels pour fournir une position, quelle que soit la position de l’utilisateur à la surface de la Terre. GNNS-wikipedia
Observer les orbites de différents systèmes de satellites sur l’animation suivante: wikipedia
Coordonnées terrestres
La géolocalisation est un procédé qui permet de repérer une personne, un objet, un lieu sur une carte (le plus souvent numérique) à l’aide de ses coordonnées géographiques qui sont :
Sa latitude (en degrés)
Sa longitude (en degrés)
Son altitude par rapport au niveau moyen de la mer (en mètres)
Le format numérique de la longitude est différent de celui de la latitude avec un chiffre significatif supplémentaire. Ceci s’explique par la valeur de l’angle qui ne dépasse pas 90° pour une latitude et qui peut atteindre 180° pour une longitude.
Les coordonnées géographiques sont traditionnellement exprimées dans le système sexagésimal, parfois noté DMS : degrés minutes secondes.
De nos jours, les notations équivalentes en degrés minutes décimales (DM) ou degrés décimaux (DD) sont également utilisées :
DMS : Degré : Minute : Seconde (49°30’00”) ;
DM : Degré : Minute (49°30,0’) ;
DD : Degré décimal (49,5000°), généralement avec quatre décimales
norme
exemple
Degrés DD
48.225833
Degrés, minutes DM
48°13,54998'
Degrés, minutes, secondes
48°13'32.9988''
Video sur les conversions DD<->DMS
Trame NMEA
Protocole NMEA 0183 : (National Marine Electronics Association): protocole utilisé par les récepteurs GPS pour fournir la localisation sous une forme de trame normalisée facilement décodable. Ces données sont mises dans un format standard :
Sur cette trame:
Quel est le caractère de début de la trame?
Quel est le séparateur entre les données?
Que signifient les lettres N, E, M?
Comment convertit-on 4836.5375 en 48°36’32.25’’? Aide: il s’agit d’une conversion DD vers DMS.
Positionner
Voici une trame affichée sur votre smartphone (utilisation de l’appli nmeaGPS):
Les graphes sont utilisés en mathématiques appliquées pour simplifier la compréhension de tous types de réseaux.
Ce sont des représentations visuelles permettant de relier des objets entre eux.
Cette théorie regroupe un ensemble de théorèmes et d’algorithmes visant à résoudre divers problèmes liés aux réseaux.
Relier des noeuds avec des arêtes
Soit un reseau constitué de 6 machines, que l’on symbolisera par 6 ronds A, B ,C ,D, E et F.
sommets d'un graphe
Sur une feuille, relier ses sommets ( pour que le graphe soit “connexe”). Imaginez plusieurs types de figures.
Selon le reseau dessiné entre ces machines, plusieurs scénarios peuvent être envisagés. Il peut y avoir une coupure de l’une des liaisons, ce qui risque d’isoler une partie du reseau, et entrainer des problèmes de fiabilité.
On peut aussi considérer le coût que représente le cablage des machines, qui augmente avec le nombre d’arêtes et leur longueur…
Questions:
Quels sont les avantages et inconvénients de chacun des graphes constuits sur le cahier (complets, en étoile, circulaires en particulier) en termes de fiabilité du reseau, et de coût?
Quel graphe montre la connexion la plus solide entre ces différentes machines?
Avec un graphe complet ( tous les sommets reliés à toutes les arêtes):
exprimer le nombre d’arêtes en fonction du nombre de sommets
calculer ainsi le nombre d’arêtes d’un graphe complet de 10, puis 20 sommets à l’aide d’un tableau .
calculer le nombre de connections qu’il faudrait pour relier directement chacun des 3 milliards d’internautes(chiffrede2015) )
Definitions et remarques:
Un graphe est un ensemble d’arêtes et de sommets. Ces sommets peuvent constituer des noeuds s’ils sont reliés à d’autres sommets par une arête.
Deux sommets sont voisins s’ils sont reliés par une arête.
Le degré d’un sommet dans un graphe est son nombre de voisins.
Un graphe est dit connexe s’il est en un seul morceau.
Un graphe complet est un graphe simple dont tous les sommets sont adjacents deux à deux.
Un chemin entre 2 sommets d’un graphe est le parcours qui relie ces 2 sommets. On peut présenter le parcours en énonçant les sommets traversés, ou bien les arêtes empruntées.
La longueur du chemin est égale au nombre d’arêtes empruntées.
il est illusoire d’imaginer que toutes les machines sur internet sont reliées 2 à 2 selon un graphe complet.
Les données echangées doivent donc transiter selon un chemin avec de nombreux sauts, de routeur en routeur.
Enoncé du premier problème sur les graphes
Le problème des sept ponts de Königsberg est connu pour être à l’origine de la topologie et de la théorie des graphes. Résolu par Leonhard Euler en 1735, ce problème mathématique se présente de la façon suivante :
il y a une île appelée le Kneiphof, entourée d’un fleuve qui se partage en 2 bras. Les bras de ce fleuve sont garnis de 7 ponts
les ponts de Konigsberg
Le problème consiste à déterminer s’il existe ou non une promenade dans les rues de Königsberg permettant, à partir d’un point de départ au choix, de passer une et une seule fois par chaque pont, et de revenir à son point de départ.
Il est possible de vérifier, de manière intuitive, que la promenade demandée n’existe pas. Ce sont au moins deux ponts, bien choisis, qu’il faudrait ajouter ou retirer pour permettre la promenade avec retour initialement cherchée.
Questions:
Que modélisent les noeuds du graphe?
Que modélisent les arêtes du graphe?
Vérifier que cette promenade n’existe pas.
Modifier le plan des ponts (avec un nombre minimum de ponts ajoutés) pour rendre cette balade possible.
Que remarque t-on alors sur la parité du nombre d’arêtes pour chacun des noeuds?
Modélisation
Euler propose une modélisation qui consiste à désigner chacune des berges par une lettre majuscule, les ponts par une lettre minuscule et à étudier l’existence de listes d’une taille donnée de lettres majuscules. Par exemple, sur la figure précédente, la liste CABD peut correspondre à un parcours de la berge C à la berge A par le pont e, puis de A vers B par le pont a, puis de B vers D par f.
L’impossibilité de passer deux fois par le même pont se traduit par l’impossibilité qu’une liste comporte plus de fois la séquence XY ou Y X qu’il n’existe de ponts entre les berges X et Y.
Pour Euler, une solution est une liste comportant exactement une lettre de plus qu’il n’y a de ponts, et répondant aux contraintes précédentes.
Testez le vous-même:
Repérer les berges par des noms de sommet (A, B, C, D). Et représenter les parcours possibles comme une liste de sommets atteints, en n’empruntant qu’une seule fois chaque pont.
Constater alors que la liste-solution n’existe pas.
Euler propose ensuite une règle pour répondre au problème général de promenades sur des ponts :
Un parcours eulérien est possible si, et seulement si, deux régions au plus ont un nombre impair de ponts y conduisant. Si deux régions ont un nombre impair de ponts y conduisant, le parcours commencera par l’une de ces deux régions.
Utilité des graphes
Implémentation
Les algorithmes développés par les mathématiciens discrets se prêtent bien à l’implémentation informatique, dans la mesure où le graphe est un objet discret aisément représentable de façon matricielle ou par listes chaînées par exemple:
Les réseaux routiers : les villes sont alors considérées comme des sommets, et les routes comme des arêtes ou des arcs.
Le web : les pages sont considérées comme les sommets, et les liens hypertextes sont les arêtes.
Les réseaux sociaux : les individus sont les sommets, et leurs connexions sont les arêtes.
Les bases de données, dans le modèle entité-relation, peuvent être représentées par un graphe orienté.
Résolution de problèmes
La théorie des graphes a donné naissance à une multitude de théorèmes et d’algorithmes. Chacun d’entre eux a pour objectif de résoudre un problème pratique.
Théorème pour la résolution du problème d’Euler: un graphe connexe admet un parcours eulérien si et seulement si ses sommets sont tous de degré pair sauf éventuellement deux d’entre eux.
Si le graphe modélise un réseau urbain (les sommets représentant les sites et les arêtes les liens de communication): par exemple, un plan de métro:
quel est le nombre minimal de changements entre deux stations données ?
quelles sont les stations que l’on peut rejoindre à partir d’une station donnée, avec un changement au plus ?
La recherche en mathématiques
La théorie des graphes a connu un essor important et a permis de modéliser de nombreux problèmes:
Le problème hamiltonien, qui peut paraître proche du problème eulérien. Il s’énonce ainsi : Existe-t-il un chemin ou un circuit passant par tous les sommets d’un graphe une et une seule fois ? Ce problème n’a pas de solution générale aujourd’hui.
Le théorème des 4 couleurs : Énoncé en 1852 par Francis Guthrie, ce problème a été résolu à la fin du vingtième siècle. Dans sa première forme, il s’énonçait ainsi : peut- on colorier avec quatre couleurs une carte géographique de telle façon que deux régions limitrophes aient une couleur différente? Voir resolution ici: villemin.gerard.free.fr
Quels problèmes peuvent resoudre les graphes pour Internet
La modélisation en graphe du reseau internet peut répondre aux questions:
tous les noeuds du graphe sont-ils accessibles? deux sites donnés peuvent-ils communiquer ?
Quels sont les chemins possibles pour relier 2 noeuds A et B?
Si l’un des chemins est rompu, existe t-il un autre chemin?
Quel est le plus court chemin pour relier 2 noeuds A et B?
Toutes ces questions peuvent être résolues grâce à un algorithme de parcours de ce graphe, dont un exemple sur cette page, avec le parcours en largeur.
La randonnée du Col des Fourches jusqu’au fort de Pelousette est décrite ici. Il s’agit d’un itinéraire dans les alpes du Sud, près du col de la Bonette.
Le but de la séance est de placer des marqueurs sur la carte IGN, afin de matérialiser l’itinéraire, comme sur l’image suivante:
PROGRAMME 1 : conversion DM => DD
DM et DD sont des formats de repères d’angles:
DM: signifie Degrès Minutes
DD: signifie Degrès Décimal
Sur l’interface Scratch de Vittascience:
Menu Var : Créer une variable que vous nommerez degres
… puis:
Menu Var : affecter à degres la valeur “ “
Menu E/S :
Choisir le bloc demander à l’utilisateur “Entrer un nombre“
Le programme devrait ressembler à ceci :
Entre les guillemets : modifier le texte : Entrer les degres :
Compléter le programme pour qu’il demande aussi les minutes et qu’il stocke la valeur dans la nouvelle variable minutes :
Opération math
Enfin, vous allez créer une nouvelle variable DD. Et lui affecter le résultat de l’opération degres + minutes / 60 :
Menu Math : choisir le premier bloc (opération +) :
Modifier et combiner 2 blocs comme celui-ci pour écrire l’opération degres + minutes / 60
Afficher le résultat
Il ne reste plus qu’à afficher le résultat avec la fonction écrire dans la console du menu E/S.
Utiliser le programme TI-CONNECT pour le transfert de fichier.
Transfert sur calculatrice TI83
Brancher la caclulatrice. Dans le logiciel TI-CONNECT, appuyer sur le bouton de transfert ordinateur => calculatrice
IDE Python
Avec le bouton prgm de la calculatrice, choisir 2: Python App
Choisir le programme PYTHON01 avec le curseur.
Les boutons du menu en bas de l’ecran sont accessibles avec chacune des touches situées au dessous.
Par exemple, touche fx pour Exécuter.
Utiliser alors le programme depuis la fenêtre du shell:
Utilisez alors votre programme pour définir les coordonnées DD du départ de la randonnée:
latitude
longitude
Départ
44°20,01612'
6°52,1109'
Remarque: il vous faudra executer une 2e fois le programme pour le calcul de la longitude. Aller dans le menu Script puis executer à nouveau le programme.
PROGRAMME 2: Créer une fonction conversion
Une meilleure approche du langage python consiste à créer une fonction, puis appeler celle-ci depuis le Shell pour afficher le résultat.
Aller sur Editer
Le script est alors le suivant:
degres=float(input('Entrer les degres :'))minutes=float(input('Entrer les minutes :'))DD=degres+minutes/60print("L'angle en notation DD est :")print(str(DD))
script affiché dans l'éditeur de la TI83
Aller sur la première ligne et insérer la définition de la fonction:
Menu Fns…: onglet Fonc: choisir 1: def fonction()
ajouter le nom de la fonction en passant en clavier alphanumérique (bouton 2nde puis alpha): def conversion():
ajouter des paramètres entre les parenthèses, que vous nommerez degres et minutes
adaptez alors le script: supprimez toutes les lignes sauf celle du calcul de DD, rectifier les indentations dans le bloc de la fonction.
ajouter l’instruction return DD à partir du menu Fns…: onglet Fonc: choisir 2: Return
Exécuter le programme
Le Shell python
Dans la fenêtre du Shell, il ne se passe rien. C’est normal, vous allez appeler la fonction avec des arguments placés:
avec le bouton var: choisir conversion (OK)
le Shell affiche le nom de la fonction.
Il faut completer avec les arguments
Voilà, vous pourrez utiliser maintenant la fonction conversion pour transformer n’importe quelle valeur du format DM vers le format DD.
Voici celles du départ et de l’arrivée de la randonnée:
latitude
longitude
Départ
44°20,01612'
6°52,1109'
Arrivée
44°20,04108'
6°51,91188'
Positionner des marqueurs sur une carte
Vous allez placer 2 marqueurs sur une carte, correspondant au départ et à l’arrivée de la randonnée.
Dans les outils de creation, choisir le marqueur: Placer des points.
Renseigner alors les coordonnées dans la barre de recherche à partir des résultats calculés en format DD (voir plus haut)
Il vous reste alors à cliquer sur le cercle-cible pour placer les 2 points départ et arrivée sur la carte.
On pourra placer d’autres points de l’itinéraire avec la même méthode…
latitude
longitude
étape 1
20,43636'
6°51,54288'
étape 2
44°20,49468'
6°51,99768'
étape 3
44°20,10228'
6°52,15908'
étape 4
44°19,81248'
6°52,28124'
étape 5
44°19,83708'
6°52,27248'
fonction de conversion android
Situation - problème
La randonnée du Col des Fourches jusqu’au fort de Pelousette est décrite ici. Il s’agit d’un itinéraire dans les alpes du Sud, près du col de la Bonette.
Le but de la séance est de placer des marqueurs sur la carte IGN, afin de matérialiser l’itinéraire, comme sur l’image suivante:
PROGRAMME 1 : conversion DM => DD
DM et DD sont des formats de repères d’angles:
DM: signifie Degrès Minutes
DD: signifie Degrès Décimal
L’editeur de programme
Pour créer un nouveau programme: Menu Fichier: New
Saisir alors le script python:
degres=float(input('Entrer les degres :'))minutes=float(input('Entrer les minutes :'))DD=degres+minutes/60print("l'angle en notation DD est :")print(DD)
Sauvegarder le programme:
Menu Fichier: Save as
Internal storage
Créer un nouveau dossier appelé python: New Folder puis saisir python
Nommer le fichier: localisation.py
Executer alors le programme avec le bouton jaune en bas de l’écran
Renseigner les valeurs de degrés et minutes pour convertir en DD:
Utilisez alors votre programme pour définir les coordonnées DD du départ de la randonnée:
latitude
longitude
Départ
44°20,01612'
6°52,1109'
Remarque: il vous faudra executer une 2e fois le programme pour le calcul de la longitude
Programme 2 : Créer une fonction conversion
Une meilleure approche du langage python consiste à créer une fonction, puis appeler celle-ci depuis le Shell pour afficher le résultat.
Modifier le programme pour créer une fonction conversion
Revenir dans l’editeur et modifier le programme pour créer une fonction:
La fonction conversion a alors 2 paramètres, degres et minutes qui devront être renseignés lors de l’appel de la fonction. Cela se fera depuis le Shell python.
Le Terminal
Depuis le menu principal, à gauche, choisir Terminal
Utiliser alors les instructions UNIX:
$ ls
$ cd python
$ python
explications…
instruction UNIX
commentaire
ls
affiche le contenu du dossier courant
cd python
changer de dossier et aller dans le dossier python
python
lancer le shell python
Le Shell python
Les instructions python seront alors saisies après les chevrons >>>
Chaque ligne saisie sera alors exécutée.
Saisir:
>>>fromlocalisationimport*>>>conversion(40,23)
Voilà, vous pourrez utiliser maintenant la fonction conversion pour transformer n’importe quelle valeur du format DM vers le format DD.
Voici celles du départ et de l’arrivée de la randonnée:
latitude
longitude
Départ
44°20,01612'
6°52,1109'
Arrivée
44°20,04108'
6°51,91188'
Positionner des marqueurs sur une carte
Vous allez placer 2 marqueurs sur une carte, correspondant au départ et à l’arrivée de la randonnée.
recherche RGPD
recherche documentaire, travail collaboratif, framapad
histoire informatique et reseaux
recherche documentaire, LibreOffice Writer
Mettre en forme RGPD
suite du travail de recherche documentaire sur le RGPD, mise en forme avec Writer
guide style
mise en forme d’un document, guide de style, libreOffice, structure
Utiliser Writer
traitement de texte, logiciel libre, contenu, structure et styles, proprietes des elements
Writer et Word
elements, proprietes, styles, similitudes dans l’utilisation des logiciels de traitement de texte
moteurs de recherche
experimenter avec un moteur de recherche
classif vivant
balises HTML, structurer le document
Les plastiques
balises HTML, structurer le document
La démocratie athenienne
balises HTML, structurer le document
La bataille de Marignan
langages web, html css, structure et mise en forme du document web
mon film prefere v1
appliquer ses connaissances pour construire une page web de zero, version SNT
mon film prefere v2
appliquer ses connaissances pour construire une page web de zero, version NSI_1
questionnaire
creer un questionnaire en ligne à destination des parents d’eleves dans une ecole elementaire. Framasoft
tableau de notes
tableau de notes, formule de calcul, etendre une selection
nobels
selectionner, ordonner, somme avec condition
analyse graphique
importer un fichier de reponses en format csv, analyse et representations graphiques
somme et moyenne sur Excel
Tableur Excel Construire une formule de calcul de moyenne Fonction somme Pour programmer la fonction SOMME sur les valeurs d’une colonne du tableau Voici un lien vers le tuto de microsoft office. cliquer dans la cellule juste sous la dernière valeur de la colonne. Ecrire debut de la formule (bien commencer la ligne par le signe =): = SOMME( puis faire une sélection étendue de toutes les valeurs de la colonne. (voir image ci-dessous) Valider avec la touche Entrer Compter le nombre de cellules Pour compter le nombre de valeurs dans le tableau, utiliser la fonction NOMBRE
tracé d’un histogramme
Tracé d’un histogramme avec Excel Un histogramme donne une représentation d’un tableau avec des effectifs, de manière très visuelle. Cela facilité grandement l’interprétation. Dans une feuille du tableur Excel: Placer dans une première ligne les etiquettes des colonnes (par exemple, renseigner le nom des matières) Placer juste au dessous les effectifs correspondant (par exemple, la matière préférée) Selectionner ensuite l’emplacement des données (ne pas prendre la première colonne, qui constitue le titre).
recherche de correlations
Recherche de corrélations Principe La recherche de correlations entre valeur d’un tableau consiste à identifier des colonnes qui semblent être interdépendantes. On doit commencer par rassembler les données dans une même table, où les réponses d’une même personne sont rassemblées dans une même ligne.
matchs OM Nice
stats sur l’ensemble des matchs Nice Marseille en Ligue 1, Excel
data.gouv maires de France
data.gouv Le site data.gouv.fr est la plateforme des données publiques françaises. Nous allons consulter les données du Répertoire National des Élus (RNE). Celui-ci a pour finalité le suivi des titulaires d’un mandat électoral. Il est renseigné et tenu à jour par les préfectures et les services du ministère de l’intérieur. Rendez vous à la page de consultation du RNE.
tableur sur calcu TI83
Utilisation de la base de données Ouvrir la base de données Aller sur la page Exoplanet.eu Pour consulter la base de données de toutes les planetes observées, cliquer sur Tous les catalogues. accès à la base de données
Notebook: variables en python: Lien vers Capytale, ou telechargement Notebook: fonctions en python: Lien vers Capytale, ou bien, si l’ENT ne fonctionne pas: telechargement, et version pdf utiliser des fonctions pour calculer sans peine les caracteristiques des planetes du systeme solaire: Notebook et fiche reponse: pdf de scratch à python
programmer une fonction python avec des blocs scratch puis recopier le programme python généré
Le framapad est un document avec editeur en ligne de la societé de logiciels libre Framasoft.
Commencer par entrer votre prénom pour vous identifier lors de votre travail d’edition.
Rédiger votre réponse: pour une seule ou plusieurs des questions posées. Préciser le numero de la question.
Une fois tous les changements terminés, marquez votre version avec une étoile pour la sauvegarder en ligne et la retrouver dans l’historique.
Enregistrer le document au format .text dans vos documents. Vous pourrez l’éditer de façon plus complète dans LibreOffice Writer dans une prochaine séance.
Recherche Documentaire: Questions
Quelles données relèvent de l’identité numérique, l’identité administrative, ou de l’indirectement nominatif?
Qu’est ce que le RGPD
Qu’est ce que la CNIL?
Qui a pour devoir de se mettre en conformité vis à vis du RGPD?
Une entreprise, pour être en conformité avec le traitement de données de ses clients, doit-elle adresser une demande auprès de la CNIL? Que doit-elle faire?
Le RGPD interdit-il l’utilisation à des fins commerciales des données?
Quelle est la différence entre une donnée, et une information sur une personne?
A partir de quelles données personnelles peut-on trouver des renseignements sur la santé et l’hygiène de vie d’une personne? Peut-on l’utiliser pour prendre des décisions sur son embauche, ou bien pour calculer le prix de sa cotisation mutuelle santé?
Un restaurant qui livre des pizzas: quelles données va-t-il avoir besoin de collecter sur ses clients? Ces données peuvent-elles être considérées comme sensibles? Si la base de données du restaurant est piratée, celui-ci est-il responsable au regard de la loi?
Que pensez-vous d’une entreprise qui utilise les données biométriques de ses employés pour contrôler leur identité et accès à leur poste de travail le matin (voir le film de science fiction Bienvenue à Gattaca)
Lorsque je surfe sur le web, à la recherche d’un article à acheter: Le prix de l’article proposé par les commerçants va-t-il evoluer au fur et à mesure de mes activités sur le web? Y-a-t-il des traces de ma navigation? Qu’est-ce qu’un tracker?
Suis-je en droit de demander à l’entreprise Google qu’elle me fournisse toutes mes traces numériques qui me concernent? Quelles seront ces traces numériques?
Données à caractère personnel
Parmi les données suivantes, certaines peuvent être classées comme relevant de:
l’identité numérique
identité administrative
indirectement nominative (qui donne l’identite de la personne, une fois effectué un recoupement d’informations)
Ce sont:
Le nom, le prenom, l’adresse
un pseudo, un mot de passe
une adresse IP
des lieux visités et géolocalisés
un panier d’achat
des clés de recherche su internet
numero de carte bancaire
numero NIR (securité sociale)
données associées à son compte de reseau social (publications, like)
Données exposée par d’autres mais nous identifiant dans un reseau social
ordonance médicale, clichés radiographiques, …
L’enregistrement de la voix de clients ou salariés par un dispositif informatique
images de personnes physiques captées par un système de vidéosurveillance
le patrimoine d’un propriétaire
…
Même des données supposées anonymes peuvent nous identifier car il existe souvent une clé de correspondance qui peut nous identifier.
Traitement des données
Definition
il s’agit de toute opération effectuée de manière automatisée appliqué à des données à caractère personnel.
Enjeux pour l’usager
Aujourd’hui, l’aspiration des individus, en termes de protection de leur vie privée est de pouvoir utiliser les services technologiques d’internet, de s’exposer personnellement (reseaux sociaux), tout en cédant une partie acceptable de leurs données personnelles. Cette part cédée doit rester raisonnable et être négociée par contrat avec les opérateurs économiques.
Le RGPD (Réglement Général pour la Protection de Données)
Définition
C’est un document qui donne un cadre légal à l’utilisation des données dans l’UE et contraint les organismes publics ou privés à certaines obligations.
Ce texte vise à définir des équilibres: protection des individus d’une part, utilisation des données à des fins commerciales ou pour des missions d’intérêt public, d’autre part.
Le RGPD n’interdit PAS l’utilisation commerciale des données.
Mais il fournit un cadre, auquel les entreprises privées, comme les administrations publiques doivent se conformer.
Obligations de conformité vis à vis du RGPD
Pour les entreprises et administrations, susceptible de TRAITER des données à caractère personnel:
devoir de tenir un registre des activités de traitement (finalités, délai de conservation et de suppression automatique, réalisation d’atude d’impact…)
obligation d’assurer une collecte lisible et transparente des données
protéger les données. Assure leur sécurité et leur confidentialité
définir un paramètre: Rester minimal dans la quantité de données et le type de données collectées
interdiction de collecter certaines catégories particulières de données (origines raciale ou ethnique, opinions politiques, convictions religieuses, appartenance syndicale)
interdiction de collecter le numero NIR (securité sociale) car celui-ci contient un certain nombre de caractéristiques qui aident au chainage des données
interdiction de collecter des données génétiques, biométriques, concerant la santé, la vie et l’orientation sexuelle.
Droit des personnes vis à vis du RGPD
Tout individu doit:
pouvoir être questionné pour demander son consentement préalable à la collecte et l’utilisation de ses données.
être informé sur la finalité du traitement qui sera effectué
dans le cas d’une collecte indirecte: être informé de la source de cette collecte, et droit de recours auprès de la CNIL
avoir droit d’accès, de rectification et de portabilité des données (c’est à dire, droit à obtenir ses données collectées dans un format structuré, lisible)
avoir droit d’effacement
avoir droit d’opposition au traitement des données à visée commerciale et de profilage
avoir des droits concernant les cookies, exploitant ses traces de navigation. Côté client, ces cookies sont stokées dans le navigateur web. L’individu doit donner son consentement sur leur utilisation, à partir d’une information claire et complète
avoir droit au deferencement: demander la suppression de liens vers des informations portant atteinte à la vie privée.
Remarques:
Il existe également un tracking côté serveur. Le client n’est alors pas en mesure d’effacer ses traces numériques, qui sont partagées le plus souvent avec des entreprises tierces (revente des données). Dans la chaine de partage des données, tout le monde est alors responsable du traitement qui sera effectué sur ces données.
De nombreux exemples montrent des manquements à ces règles sur la protection des données et leurs conséquences: L’affaire Facebook pendant l’élection américaine, qui a vu gagner le président Trump en est un tristement célèbre, même si cela ne concernait pas le territoire d’influence de la CNIL et de son équivalent européen. Au niveau fançais: les affaires Foncia, Acadomia…
La CNIL
Definition
Commission Nationale pour l’informatique et les libertés. La CNIL est la premiere autorité administrative instaurée en France (1978) à la faveur de l’adoption de la loi “informatique et libertés”.
Les actions de la CNIL
La CNIL exerce un pouvoir de contrôle et de sanctions pour la protection des données. Elle est indépendante et ne reçoit d’instruction d’aucune autorité publique.
Tout citoyen peut s’adresser à la CNIL pour la saisir d’une plainte.
La CNIL réalise des
controles d’audit, qui sont programmés, sur des organismes privés comme publics.
contrôles de contentieux à partir de plaintes, de dénonciations anonyme ou de tout autre moyen qui lui aurait permi de prendre connaissance d’un manquement au RGPD
Sanctions prises
Lors d’un manquement avéré, la CNIL peut:
faire suspendre les flux de données adressés à un destinataire
prendre des sanctions pécunières
prendre des sanctions d’image: publication sur le site de la CNIL et dans le Journal Officiel. Les répercussions peuvent être importantes (risque réputationnel)
Liens
cours de Seconde SNT sur la protection des données, illustré de quelques videos et autres liens
Ouvrage: La protection des données personnelles, le RGPD et la nouvelle loi française, Guillaume Desgens-Pasanau, ed. LexisNexis
histoire informatique et reseaux
Partie 1: Histoire de l’informatique et des reseaux
Dans ce TP nous allons créer une petite chronologie de l’informatique à l’aide du traitement de textes LibreOffice Writer.
créer un document texte qui rassemble 3 à 6 dates par période de l’histoire de l’informatique et d’internet. Faites un choix pertinent pour chacune des dates et descriptions. Choisir ce qui selon vous, résume le mieux chaque période.
Consignes
Le document ne doit pas excéder DEUX pages A4.
Vous utiliserez des styles pour le mettre en forme:
Titre principal pour le titre du document: «Chronologie de l’informatique»
Titre 1 pour chacune des phases de l’histoire de l’informatique:
«L’époque des pionniers»
«Les débuts de la micro-informatique»
«L’ère d’Internet et du World Wide Web»
«L’ère de la mobilité et des données partagées»
Les dates et leur description sont écrites sous forme d’une liste non-ordonnée avec le Style de paragraphe par défaut.
Sauvegarder votre fichier sous le titre histoire_informatique_reseaux dans le dossier Documents/Devoirs/tixidor/
Remarque: Vous pouvez coller du texte issu d’une page en supprimant sa mise en forme grâce au collage spécial <CTRL+MAJ+V>(ou bien clic droit: coller sans Formatage)
Il est nécessaire de séparer l’écriture du contenu du document (Partie 1) de celui de sa mise en forme (Partie 2).
Partie 2: mise en forme du document
Pour être lisible, un texte doit comporter une certaine hiérarchie.
Définir les éléments, structurer le document
Utiliser des niveaux de titres pour structurer votre document (Titre1, Titre2, Titre3…).
Le document initial
Choisir Titre 1 pour le titre principal
Choisir Titre 2 pour chacune des phases de l’histoire de l’informatique: Les prémices de l’informatique, …
Choisir le Style Titre 3 pour les dates relatives aux machines et leurs systèmes d’exploitation.
Le document devrait maintenant ressembler à ceci
Créer ensuite DEUX nouveaux Styles enfants de Titre 3, comme sur l’image ci-dessous.
L’un des ces nouveaux Style servira à mettre en relief les Algorithmes
L’autre pour les reseaux et les programmes relatifs à ces reseaux.
Seule la propriété couleurs des Styles enfants diffèrent de Titre 3. Les autres propriétés sont héritées.
Ajouter une numérotation aux chapitres (phases de l’histoire)
Créer un épigraphe pour chaque phase de l’histoire
L’épigraphe est une courte citation placée au début d’un ouvrage ou d’un chapitre, et qui permet d’en indiquer l’esprit, de résumer son contenu.
Personnaliser le style
Vous allez personnaliser les Styles utilisés dans votre document. Vous modifierez les propriétés des différents éléments. Un exemple de document stylisé est donné ci-dessous:
personnalisation des propriétés couleur, alignement, police, ...
Styliser le document de manière personnelle
Voici un modèle utilisé pour un mémoire (document long), pour sciences politiques Lille:
Exemple de document - rediger un mémoire - sciencespo-lille.eu
Les manières de mettre en forme un document sont très variés, les choix de design sont personnels. Dans tous les cas, il sera nécessaire de modifier les propriétés des Styles en modifiant leurs valeurs.
Utiliser les tutoriels ci-dessous.
Modifier le style d’un élément ou en créer un nouveau
Méthode 1:
Depuis la fenêtre des Styles (à droite), sélectionner l’un des élements, comme par exemple Style de paragraphe par défaut. Choisir dans le menu: Nouveau ou Modifier
Nouveau: cela créé un nouvel objet fils de celui sélectionné, qui s’ajoute à la liste des Styles
Modifier: cela ouvre la fenêtre de modification du Style, que l’on peut aussi atteindre depuis la barre de menu du haut (Styles > choisir Editer le Style). La nouvelle fenêtre contient alors toutes les propriétés modifiables pour ce Style, classées par onglet.
Méthode 2:
Sélectionner dans la page l’un des éléments dont vous souhaitez modifier le style. Modifier avec les boutons de la barre d’icones (en haut), ou bien celle des proriétés de style (à droite).
barre d'icones
Puis cliquer sur le bouton Mettre à jour le Style sélectionné.
Ce bouton se trouve près du menu des styles de la barre d'icones
Modifier l’une des propriétés de Titre 1
Si vous souhaitez modifier la couleur des Titre 1
Dans la partie Style (fenêtre à droite), dérouler le sous menu Titre
Choisir Titre 1 , puis Modifier. Cela ouvre la fenêtre d’Edition.
Le but est alors de retrouver la bonne Propriété.
Choisir l’onglet Effets de caractère. Puis la propriété Couleur de Police, dont vous pouvez modifier la valeur.
Writer est l’un des logiciels de la suite bureautique LibreOffice.
Cette suite bureautique est libre et gratuite, elle est dérivée du projet OpenOffice.org, créée et gérée par The Document Foundation.
LibreOffice est notamment soutenue par la Fondation pour le logiciel libre et rassemble une grande partie de l’ancienne communauté d’OpenOffice.org.
En France, LibreOffice est intégré au socle interministériel de logiciels libres de l’État.
L’interface utilisateur est disponible en 114 langues.
Dans un logiciel de traitement de texte, on fait simultanément les 2 actions suivantes:
on insère du contenu dans une page
on formate le contenu.
Que signifie: Formater le contenu?
Mettre en forme un document textuel demande de connaitre le nom et la nature des objets et des fonctions utilisés:
feuille de Style
Objets paragraphes, Titre 1, Titre 2, …, listes.
Tous ces objets sont accessibles dans le bandeau de droite
Vous allez identifier ou ajouter ces différents éléments éléments au document:
Les paragraphes
Le titre
Le sous-titre
Les chapitres (HEADER) de niveau 1, niveau 2, etc
Les listes
L’en-tête et le pied de page
La bibliographie
Le sommaire
Travail demandé
Copier le contenu du Framapad. Coller en faisant collage special afin d’éliminer toutes les mises en forme.
Reconstruire les paragraphes
Utiliser les niveaux de titres pour structurer votre document (Titre1, Titre2, Titre3…).
Numéroter les sous-titres (Menu Outils> Numérotation des chapitres).
Insérer une image
Ajouter une bibliographie ou une sitographie
… et s’il vous reste du temps, commencer à voir comment personnaliser les styles: Lien vers la page utilisation avancée de Writer
Utilisation basique de Writer
Un tutoriel sur l’utilisation avancée de Writer:
Youtube - LibreOffice Writer 1/11 : Mettre en forme le style principal
Identifier les titres de niveau 1, 2, …
Titre de niveau 1: Positionner le curseur sur la ligne que vous voulez identifier comme un titre de niveau 1
Dans la partie Style (fenêtre à droite), dérouler le sous menu Titre
Et faire un double-clic sur Titre 1. L’élément devient alors un Titre 1, et prend le style associé, c’est à dire les propriétés suivantes, visible dans la barre d’outils (en haut):
police: Liberation Serif
taille: 24 pt
decoration: bold
Par defaut, un élément du document est de type Paragraphe.
Ajouter une numérotation
Si vous souhaitez ajouter un numéro aux éléments de type Titre 4:
Ouvrir le menu Outils de la barre des menus et choisir numérotation des chapitres:
Dans la fenêtre, choisir l’onglet numérotation et paramétrer pour démarrer une numérotation 1,2,3 pour les titres de niveau 4:
Vous allez ajouter 3 à 6 liens qui ont été utiles pour la rédaction du contenu.
Une référence bibliographique doit indiquer toutes les informations indispensables à l’identification d’un document ou d’un texte, et ce, qu’il soit accessible en version papier ou en ligne. Le format de la référence varie légèrement selon le document. Essayez de vous y conformer.
Référencer une page web
Auteur identifié
Nom, P. Titre de la page. Nom du site. Consulté le Date sur URL
Exemple:
-------
Leterme, C. (2020, janvier 31). Tout savoir sur la publication d’un article scientifique. Scribbr. Consulté le 15 mars 2023 sur https://www.scribbr.fr/article-scientifique/publication-article-scientifique/
Sans auteur, sans date
Exemple:
-------
Tarte aux pommes. (s. d.). Marmiton. https://www.marmiton.org/recettes/recette_tarte-aux-pommes_18588.aspx
Référencer une publication
Un article d’encyclopédie ou d’une revue en ligne:
Nom, P. (Année). Titre de l’article. Dans Titre de l’encyclopédie. URL
Exemple:
-------
Ramade, F. (2022). Écotoxicologie. Dans Encyclopædia Universalis. http://www.universalisedu.com.srvext.uco.fr/encyclopedie/ecotoxicologie/
Auteur non identifié:
Si l’auteur n’est pas identifié car il s’agit d’une institution ou d’un organisme, son nom remplace celui de l’auteur.
Exemple:
-------
Ademe. (2021). Rapport de diagnostic-Actualisation de l’étude d’évaluation des services vélos. https://librairie.ademe.fr/mobilite-et-transport/4934-diagnostic-d-evaluation-des-services-velos.html
Un texte réglementaire en ligne:
Titre de l’arrêté. (Année). JORF No, Jour mois, 2021. Texte no. Http
(à lire) Recommandations utiles pour des documents longs
Insérer des sauts de pages avant les titres de niveau 1 (Menu Style de paragraphe: Titre1)
Utiliser peu de polices, une pour les titres et une pour le texte. Utiliser des polices de qualité bien lisibles par exemple: Times new Roman(serif pour le texte), Arial(sans serif pour les titres).
Utiliser les images avec parcimonie et numéroter et légender les figures(clic droit sur l’image: Insérer une légende). Pensez à citer la source, et respecter les droits d’auteur sur l’image.
Numéroter les pages(Dans le pied de page, Insertion> Champ > Numéro de page).
Faire une page de garde non numérotée avec le style de page Première Page.
Insérer en deuxième page la table des matières générée automatiquement à partir des titres(MenuInsertion > Table des matières).
Pour la bibliographie, l’insertion de notes de bas de page ou de fin peut suffire(Menu Insertion > Note de bas de page/ de fin).
Pour être lisible, un texte doit comporter une certaine hierarchie. Cela amène de la clarté, mais, aussi, cela sera utile si l’on veut intégrer une table des matières ou un sommaire.
Il est nécessaire de séparer le travail de la forme du document de celui du contenu. Et de bien connaitre les différents éléments du document.
Guide de style pour le mémoire
Les règles à suivre
Utiliser les niveaux de titres pour structurer votre document (Titre1, Titre2, Titre3…).
Numéroter les titres et sous-titres(Menu Outils> Numérotation des chapitres).
Insérer des sauts de pages avant les titres de niveau 1 (Menu Style de paragraphe: Titre1)
Utiliser peu de polices, une pour les titres et une pour le texte. Utiliser des polices de qualité bien lisibles par exemple: Times new Roman(serif pour le texte), Arial(sans serif pour les titres).
Utiliser les images avec parcimonie et numéroter et légender les figures(clic droit sur l’image: Insérer une légende). Pensez à citer la source, et respecter les droits d’auteur sur l’image.
Numéroter les pages(Dans le pied de page, Insertion> Champ > Numéro de page).
Faire une page de garde non numérotée avec le style de page Première Page.
Insérer en deuxième page la table des matières générée automatiquement à partir des titres(MenuInsertion > Table des matières).
Pour la bibliographie, l’insertion de notes de bas de page ou de fin peut suffire(Menu Insertion > Note de bas de page/ de fin).
Pensez à exporter votre document au format pdf pour le partager.
TP1 - Evaluer la forme d’un mémoire
Le modèle
A vous de jouer: Repérez ces différents éléments dans le document suivant:
Vademecum - rediger un mémoire - sciencespo-lille.eu
Evaluation
Ouvrir ensuite les
rapports
de stage d’observation et de pratique accompagnée de Julie et Marion. Ces deux documents, respectent-ils TOUTES les règles du guides de style présentés plus haut?
TP2 - Mettre en forme un document
On s’aidera du tutoriel pour LibreOffice Writer à l’adresse suivante:
Youtube - LibreOffice Writer 1/11 : Mettre en forme le style principal
Téléchargez ce document et modifiez le pour le présenter avec un Style inspiré du mémoire - sciencespo-lille.eu:
Créer des éléments particuliers dans le texte: ajouter un Titre, un Sous-titre, des Chapitres de niveau 1, 2…
Modifier les Styles
Ajouter une ou plusieurs images
Ajouter un sommaire, un épigraphe
Ajouter un en-tête, un pied de page
Remarque: Si on a malencontreusement stylé du texte par le menu du haut, utiliser le raccourci CTRL+M pour «Effacer le formatage direct» (ou par le menu Format)
Les éléments du document
Voici la liste des éléments mentionnés dans le guide de style. On retrouve la plupart de ces éléments comme des objets communs aux logiciels de traitement de texte (Word, Writer).
Le titre
Le sous-titre
Les chapitres (HEADER) de niveau 1, niveau 2, etc
Les paragraphes
Les listes
L’en-tête et le pied de page
L’épigraphe
L’épigraphe est une courte citation placée au début d’un ouvrage ou d’un chapitre, et qui permet d’en indiquer l’esprit.
La table des matières correspond à une liste complète des parties et des sous-parties d’un document.
La table des matières
La table des matières (table of contents en anglais) est placée à la fin de l’ouvrage. Elle détaille l’ensemble des divisions d’un document.
Le sommaire
Le sommaire est généralement plus succinct et ne reprend pas forcément toutes les sous-parties. Le sommaire propose un résumé des parties à venir dans le document et se situe ainsi au début de celui-ci.
Réutiliser ses Styles personnalisés
A l’ouverture d’un nouveau document, les Styles sont remis à ceux d’origine. Pour retrouver ceux que vous avez déjà définis, il faut charger les Styles à partir de votre ancien document:
Voir ici les explications
.
Correcteur orthographique
Le logiciel Writer comprend un correcteur grammatical et d’orthographe. On peut aussi en ajouter un (par ex. l’extension Grammalecte. Utilisez le, il vous permettra d’améliorer grandement la qualité de votre compte-rendu(fautes d’orthographe, formes grammaticales, insertion d’espaces insécables…).
Cette fiche montre les similitudes de conception d’un document:
Textuel avec LibreOffice Writer
Pour le Web, en langage HTML
Un document réponse est à télécharger et compléter:
Document à compléter
Partie 1: Formater le texte d’un document avec Writer
Mettre en forme un document textuel demande une certaine maitrise du logiciel, mais surtout, connaitre le nom des objets et des fonctions utilisés:
feuille de Style
Objets paragraphes, Titre 1, Titre 2, …, listes.
Ainsi que le nom des propriétés de ces objets:
Police, taille de la police, couleur
indentation, surlignage, encadré
…
Remarque: Le logiciel appelle ces éléments et objets des Styles. Nous préférons conserver les termes objets ou éléments pour désigner les paragraphes, Titre 1, …, comme il est d’usage en HTML (voir partie 2).
Choisir une feuille de style à l’ouverture
A l’ouverture du logiciel Writer, vous pouvez choisir parmi plusieurs styles prédéfinis. Mais que se passe-t-il si vous avez besoin d’un style différent tel qu’un style poème qui n’est pas dans la fenêtre Styles et formatage?
Une fois votre document ouvert, vous pouvez toujours changer de feuille de style. Pour afficher les styles sous Libre Office : Choisissez dans la barre des menus (en haut): Styles > Charger les styles.
Modifier le style d’un élément ou en créer un nouveau
Méthode 1:
Depuis la fenêtre des Styles (à droite), sélectionner l’un des élements, comme par exemple Style de paragraphe par défaut. Choisir dans le menu: Nouveau ou Modifier
Nouveau: cela créé un nouvel objet fils de celui sélectionné, qui s’ajoute à la liste des Styles
Modifier: cela ouvre la fenêtre de modification du Style, que l’on peut aussi atteindre depuis la barre de menu du haut (Styles > choisir Editer le Style). La nouvelle fenêtre contient alors toutes les propriétés modifiables pour ce Style, classées par onglet.
Méthode 2:
Sélectionner dans la page l’un des éléments dont vous souhaitez modifier le style. Modifier avec les boutons de la barre d’icones (en haut).
Puis cliquer sur le bouton Mettre à jour le Style sélectionné.
Ce bouton se trouve près du menu des styles de la barre d'icones
Modifier l’une des propriétés de Titre 1
Si vous souhaitez modifier la couleur des Titre 1
Dans la partie Style (fenêtre à droite), dérouler le sous menu Titre
Choisir Titre 1 , puis Modifier. Cela ouvre la fenêtre d’Edition.
Le but est alors de retrouver la bonne Propriété.
Choisir l’onglet Effets de caractère. Puis la propriété Couleur de Police, dont vous pouvez modifier la valeur.
Créer un élément pour insérer des scripts
Les scripts sont des programmes informatiques. Leur format suit des règles précises, et ceux-ci ne doivent pas être reformatés par le logiciel Writer. Leur indentation doit être conservée, la casse (minuscule / majuscule) aussi.
Cela peut nécéssiter la création d’un nouvel élément dans Writer. Cela permettra d’avoir un format personnalisé, comme une nouvelle police de caractères. Souvent, celle utilisée pour les scripts est Courier New, en gras.
On peut aussi faire un collage du script avec la coloration syntaxique highlight). Le logiciel en ligne highlight.hohli.com permet de faire cela. Coller le script dans la fenêtre, choisir le langage, et copier le texte mis en couleur avant de la coller dans Writer. Puis utiliser le nouveau Style personnalisé pour le formater (script).
Ajouter une numérotation
Si vous souhaitez ajouter un numéro aux éléments de type Titre 4:
Ouvrir le menu Outils de la barre des menus et choisir numérotation des chapitres:
Dans la fenêtre, choisir l’onglet numérotation et paramétrer pour démarrer une numérotation 1,2,3 pour les titres de niveau 4:
Ce TP montre les similitudes de conception d’un document:
Textuel avec Word/LibreOffice Writer
Pour le Web, en langage HTML
Formater le texte d’un document
Mettre en forme un document textuel demande une certaine maitrise du logiciel, mais surtout, connaitre le nom des objets et des fonctions utilisés:
feuille de Style
Objets paragraphes, Titre 1, Titre 2, …, listes.
Ainsi que le nom des propriétés de ces objets:
Police, taille de la police, couleur
indentation, surlignage, encadré
…
Remarque: Le logiciel appelle ces éléments et objets des Styles. Nous préférons conserver les termes objets ou éléments pour désigner les paragraphes, Titre 1, …, comme il est d’usage en HTML (voir partie 2).
Microsoft Word
A vous de jouer: Télecharger et ouvrir le document textuel sur
les plastiques
. Copiez l’ensemble du texte (CTRL + a, CTRL + c) et collez-le dans un nouveau document Word CTRL + V)
En vous inspirant de la video suivante, mettre en forme le document en suivant la méthode proposée.
video - youtube - separation contenu, structure, forme
Ci-dessous, certains travaux d’élèves sont proposés en exemple:
Pour modifier plus grandement la structure, il faut utiliser des sections.
L’editeur de texte Word permet aussi de placer une partie du contenu sur plusieurs colonnes. Le logiciel place alors des sections dans le document, comme expliqué dans le tuto suivant: tuto unilim.fr.
Libre Office Writer
Modifier le style d’un élément ou en créer un nouveau
Méthode 1:
Depuis la fenêtre des Styles (à droite), sélectionner l’un des élements, comme par exemple Style de paragraphe par défaut. Choisir dans le menu: Nouveau ou Modifier
Nouveau: cela créé un nouvel objet fils de celui sélectionné, qui s’ajoute à la liste des Styles
Modifier: cela ouvre la fenêtre de modification du Style, que l’on peut aussi atteindre depuis la barre de menu du haut (Styles > choisir Editer le Style). La nouvelle fenêtre contient alors toutes les propriétés modifiables pour ce Style, classées par onglet.
Méthode 2:
Sélectionner dans la page l’un des éléments dont vous souhaitez modifier le style. Modifier avec les boutons de la barre d’icones (en haut).
Puis cliquer sur le bouton Mettre à jour le Style sélectionné.
Ce bouton se trouve près du menu des styles de la barre d'icones
Modifier l’une des propriétés de Titre 1
Si vous souhaitez modifier la couleur des Titre 1
Dans la partie Style (fenêtre à droite), dérouler le sous menu Titre
Choisir Titre 1 , puis Modifier. Cela ouvre la fenêtre d’Edition.
Le but est alors de retrouver la bonne Propriété.
Choisir l’onglet Effets de caractère. Puis la propriété Couleur de Police, dont vous pouvez modifier la valeur.
Créer un élément pour insérer des scripts
Les scripts sont des programmes informatiques. Leur format suit des règles précises, et ceux-ci ne doivent pas être reformatés par le logiciel Writer. Leur indentation doit être conservée, la casse (minuscule / majuscule) aussi.
Cela peut nécéssiter la création d’un nouvel élément dans Writer. Cela permettra d’avoir un format personnalisé, comme une nouvelle police de caractères. Souvent, celle utilisée pour les scripts est Courier New, en gras.
On peut aussi faire un collage du script avec la coloration syntaxique highlight). Le logiciel en ligne highlight.hohli.com permet de faire cela. Coller le script dans la fenêtre, choisir le langage, et copier le texte mis en couleur avant de la coller dans Writer. Puis utiliser le nouveau Style personnalisé pour le formater (script).
Ajouter une numérotation
Si vous souhaitez ajouter un numéro aux éléments de type Titre 4:
Ouvrir le menu Outils de la barre des menus et choisir numérotation des chapitres:
Dans la fenêtre, choisir l’onglet numérotation et paramétrer pour démarrer une numérotation 1,2,3 pour les titres de niveau 4:
creer un questionnaire en ligne à destination des parents d’eleves dans une ecole elementaire. Framasoft
Sous-sections de publier
classif vivant
TP HTML/CSS n°2 - La classification du vivant
Rappels : Balises et règles CSS
Tableau récapitulatif des balises HTML
Balise
Utilisation
Syntaxe
<h1>
Titre principal
<h1>Mon titre</h1>
<h2>
Titre de section
<h2>Ma section</h2>
<h3>
Sous-titre
<h3>Mon sous-titre</h3>
<p>
Paragraphe
<p>Mon texte...</p>
<a>
Lien hypertexte
<a href="URL">Texte du lien</a>
<img>
Image
<img src="nom_image.jpg">
<figure>
Container pour image
<figure>...</figure>
<figcaption>
Légende d’image
<figcaption>Texte</figcaption>
<div>
Container / bloc
<div>...</div>
<blockquote>
Citation
<blockquote>...</blockquote>
<strong>
groupe de mots en gras
<strong>...</strong>
Principales règles CSS utiles
Propriété
Effet
Exemple
color
Couleur du texte
color: blue;
background-color
Couleur de fond
background-color: lightgreen;
font-size
Taille du texte
font-size: 20px;
font-family
Police de caractères
font-family: Arial, sans-serif;
text-align
Alignement du texte
text-align: center;
width
Largeur
width: 80%;
margin
Marges externes
margin: 20px;
padding
Marges internes
padding: 10px;
border
Bordure
border: 2px solid black;
display: flex;
Placer côte à côte
display: flex;
Structure de base d’un document HTML
<!DOCTYPE html><html><head><metacharset="utf-8"><title>Titre de la page</title></head><style>/* Vos règles CSS ici */</style><body><main><!-- Votre contenu ici --></main></body></html>
Consignes du TP
Vous allez créer une page web sur la classification du vivant en utilisant vos connaissances en HTML et CSS.
Étape 1 : Créer le fichier
Ouvrez Notepad++
Copiez le texte de contenu ci-dessous
Enregistrez le fichier sous le nom classification.html dans vos Documents
Étape 2 : Structurer le document
En vous aidant du tableau récapitulatif :
Ajoutez la structure de base du document HTML (doctype, html, head, body, main)
Identifiez et ajoutez les balises appropriées pour :
Placez-la dans le même dossier que votre fichier HTML
Insérez l’image dans le document avec une légende appropriée
Utilisez un container <div style="display:flex;"> pour placer l’image à droite du paragraphe concernant “Les arbres phylogénétiques”
Étape 4 : Styliser la page
Créez des règles CSS pour :
Donner un style particulier au titre principal (police, couleur, taille, centrage)
Définir une largeur et une couleur de fond pour le <main>
Adapter les dimensions de l’image et de son paragraphe associé
Personnaliser l’apparence des légendes d’images
Ajouter des bordures et marges si nécessaire
Objectif visuel : Obtenir une page lisible, structurée et esthétique.
Texte de contenu à structurer
La classification du vivant
Qu'est-ce que la classification du vivant ?
La classification du vivant est une science qui a pour objet de regrouper les êtres vivants par catégories. Le système actuel repose sur la notion d'évolution et de parenté entre les espèces. On classe ensemble les êtres vivants qui partagent un ancêtre commun récent. Cette approche s'appelle la classification phylogénétique.
Les critères de classification
Pour classer les êtres vivants, les scientifiques comparent leurs caractères, c'est-à-dire leurs caractéristiques observables : présence d'un squelette interne, de plumes, de poils, d'écailles, type de reproduction, etc. Plus deux êtres vivants partagent de caractères en commun, plus ils sont proches sur le plan de l'évolution. Ces caractères partagés sont appelés caractères dérivés et ils témoignent d'une origine commune.
Les arbres phylogénétiques
Les relations de parenté entre les espèces sont représentées sous forme d'arbres phylogénétiques, aussi appelés arbres du vivant. Chaque branche de l'arbre représente un groupe d'êtres vivants partageant des caractères communs. Les nœuds de l'arbre correspondent aux ancêtres communs hypothétiques. Plus on remonte dans l'arbre, plus on retrouve des ancêtres communs à de nombreux groupes d'organismes.
L'importance de la classification
La classification du vivant permet aux scientifiques du monde entier de parler le même langage lorsqu'ils étudient la biodiversité. Elle aide à comprendre l'histoire évolutive de la vie sur Terre et à identifier les relations entre les différentes formes de vie. Cette connaissance est essentielle pour la conservation des espèces et pour mieux comprendre comment la vie s'est diversifiée au cours des temps géologiques.
Sitographie
Article adapté de la page Classification phylogénétique du vivant consultée le 15 janvier 2024 sur Wikipédia : https://fr.wikipedia.org/wiki/Classification_phylog%C3%A9n%C3%A9tique_du_vivant
Image à télécharger
Pour ce TP, vous utiliserez une image d’arbre phylogénétique simplifié.
Recherche de l’image :
Rendez-vous sur Wikimedia Commons ou Wikipedia
Recherchez “arbre phylogénétique” ou “phylogenetic tree”
Choisissez une image libre de droits
Téléchargez-la et enregistrez-la sous le nom arbre.jpg dans le même dossier que votre fichier HTML
Critères de réussite
✓ Le document HTML est valide et s’affiche correctement dans le navigateur
✓ Toutes les balises de structure sont présentes (h1, h2, p)
✓ Le lien est fonctionnel
✓ L’image est visible avec sa légende
✓ L’image est placée à droite d’un paragraphe
✓ Des règles CSS personnalisées sont appliquées
✓ La mise en page est cohérente et agréable visuellement
Bonus : Ajoutez une couleur de fond différente pour les titres h2, ou créez une bordure autour des images.
Bon courage !
Les plastiques
Découverte du langage HTML
docx, odt, txt et html: différents documents textuels
Les fichiers aux extensions docx et odt permettent d’écrire et présenter du texte. La structure du document se fait à l’aide de boutons d’options proposés par le logiciel. Le rendu visuel de la page est présenté par le logiciel au fur et à mesure de sa construction.
Pour la creation d’une page web, c’est différent. On utilise un editeur HTML, comme notepad++.
Dans l’editeur, pour structurer le contenu textuel, il n’y a pas de boutons pour choisir les propriétés des éléments. Il faut ajouter DANS LE DOCUMENT des métadonnées. Cela se fait d’une manière très speciale avec le html, à l’aide de BALISES. C’est ce que nous allons voir ici.
Pour afficher la page, il faudra retrouver la page à l’aide de l’explorateur, sur votre disque dur, et l’ouvrir avec un 2e outil, le navigateur.
Le HTML : Document pour le Web
Un document pour le Web est constitué d’un ou plusieurs fichiers de type texte. Le fichier aura pour extension .html. Un fichier .html doit être ouvert avec un navigateur.
La manière avec laquelle vous allez construire ce document suit les même étapes que la rédaction d’un document textuel. Mais ici, les instructions de mise en page seront ajoutées au contenu, dans le même fichier.
Le langage HTML s’occupe de la structure du document, grâce à des balises qui intègrent le contenu.
Format de document
A vous de jouer: Télecharger et ouvrir le document textuel sur
les plastiques
. Copiez l’ensemble du texte (CTRL + a, CTRL + c)
Dans un editeur de texte: Rechercher parmi les logiciels installés: Bloc notes, Notepad, ou mieux, Notepad++ (ajoute la coloration syntaxique): coller le texte. Sauvegarder dans vos Documents avec le nom plastiques.html
Ouvrir à l’aide d’un navigateur: Double clic sur le document depuis l’explorateur windows, ou bien, depuis le menu fichier du navigateur: Ouvrir.. et rechercher le document.
Problèmes:
On obtient alors un document qui n’a aucune structure
De plus, avec certains navigateurs, certains caractères ne sont pas reconnus et cela peut donner le rendu suivant:
fichier texte non formaté ouvert avec un navigateur
On va résoudre certains de ces problèmes en déclarant le format d’encodage des caractères. Cette information est très importante pour le navigateur.
Au début du document html: Ajouter avec l’editeur les lignes suivantes:
<!DOCTYPE html><html><head><metacharset="utf-8"><title>page principale</title></head><body><section>Le plastique, une « antiquité » !
Plusieurs siècles av. J.C, les hommes utilisaient déjà ...
Ajouter aussi les lignes suivantes en FIN de document:
</section></body></html>
Navigateur:
Recharger la page (CTRL + r). Que remarquez vous?
Dans le fichier html. Remplacer <meta charset="utf-8"> par <meta charset="us-ascii">. Recharger la page. Que remarquez vous? Lequel des 2 encodages, us-ascii ou utf-8 est le plus adapté pour présenter les caractères.
Sélectionner le bon encodage pour la suite de votre travail.
Définir des éléments dans la page
Pour créer un paragraphe, le contenu devra être inséré entre une balise de début <p> et une balise de fin </p>.
Les autres balises principales sont:
Titre 1: <h1> ... </h1>
Titre 2: <h2> ... </h2>
Titre 3: <h3> ... </h3>
Bloc de citation: <blockquote> ... </blockquote>
liens: <a> ... </a>
Où les ... signifient le contenu.
Balises HTML: modifier la structure du document à l’aide des balises HTML:
ajouter la balise h1 pour le titre principal
ajouter les balises h2 pour les titres des chapitres
ajouter les balises p pour les paragraphes
ajouter les balises a pour les liens: Le lien se trouve en fin de document dans cet exemple.
Il s’agit du texte: Article issu de la page histoire du plastique de cabriolice.com https://www.carbiolice.com/blog/lhistoire-du-plastique-en-15-dates-cle/
Identifier l’URL de redirection (l’adresse du lien): https:/ ... dates-cle/
Identifier la cible du lien (le mot sur lequel vous devez cliquer): histoire du plastique
Remplacer le texte non formaté par le mélange de texte et de balises suivant:
Article issu de la page <a href="https://www.carbiolice.com/blog/lhistoire-du-plastique-en-15-dates-cle/">histoire du plastique</a> de cabriolice.com
Questions: Dans les instructions de la balise <a>:
où se place la cible du lien?
où se place l’adresse du lien?
5. Ajouter un autre lien
Placer après cette dernière ligne un autre lien, vers la page de wikipedia sur les matières plastiques par exemple.
Navigateur: Recharger la page (CTRL + r). Que remarquez vous? Les liens sont-ils actifs lorsque l’on clique dessus?
Ajouter une image
L’ajout d’image diffère de la procédure d’un logiciel d’edition de texte comme Word ou Writer. Ici, on n’insère pas l’image elle-même, mais on indique son adresse sur le net. La syntaxe est la suivante:
<imgsrc="https://adresse_sur_le_net.jpg">
On choisira une image libre d’être diffusée, comme par exemple celle sur le site wikipedia d’adresse:
Faites référence à l’auteur de l’image si vous l’identifiez, ou bien la page dont est issue l’image, à l’aide d’un élément html qui suivra l’image. On peut utiliser une balise <figcaption> ... légende ... </figcaption>.
production de granulés de polymères - image de la page *Matières plastiques* (wikipedia)
Modifier les styles des éléments
Les instructions de style se mettent entre les balises <style>. Ces balises seront placées après la fermeture </head> et avant l’ouverture du contenu <body>
Créer un lien depuis la page 1 vers la page 2, puis de la page 2 vers la page 1.
Cette fois-ci, vous allez créer des liens internes (entre documents d’un même site internet). Vous allez utiliser des adresses relatives entre les pages. Deux possibilités:
Supposons que page1.html et page2.html sont dans le même dossier: Pour créer un lien de la page 1 vers la page 2, la balise lien s’écrira: <a href="page2.html">Lien vers la page 2</a>
Si les page1.html et page2.html ne sont pas dans le même dossier, il faudra utiliser le chemin relatif: <a href="chemin/page2.html">Lien vers la page 2</a>
Le HTML s’occupe de la structure du document, grâce à des balises qui intègrent le contenu.
Formats de document
Démocratie athénienne
Les origines de la démocratie athénienne
Au vie siècle av. J.-C., les cités du monde grec sont confrontées à une grave crise politique. Pour répondre à cette crise, de nombreuses cités modifient radicalement leur organisation politique. À Athènes, un ensemble de réformes amorce un processus débouchant au ve siècle av. J.-C. sur l'apparition d'un régime politique inédit : une sorte de démocratie pour les hommes libres mais avec la continuation de l'esclavage.
La démocratie athénienne
La démocratie athénienne désigne le régime politique de démocratie directe mis en place progressivement dans la cité d'Athènes durant l'Antiquité et réputée pour être l'ancêtre des démocraties modernes. Le terme démocratie vient des mots grecs δῆμος / dêmos («le peuple») et κράτος / krátos («la puissance, le pouvoir»). Il s'agit donc d'un régime où les décisions sont prises par le peuple.
La cité
Athènes est fondée formellement vers 750 av. J.-C. par synœcisme de plusieurs agglomérations partiellement préservées de l'invasion des Doriens.
Le site est choisi pour la forteresse naturelle que représente l'Acropole ; les habitants peuvent résister aux hordes de pillards qui menacent la région, augmentant avec les années sa fortification. À partir de 510 av. J.-C., cette fonction défensive est abandonnée, le lieu étant consacré aux cultes et notamment celui d'Athéna, déesse protectrice d'Athènes. Des remparts encerclent à partir de 478 av. J.-C. la ville et son port, le Pirée.
Quelques gymnases et écoles de philosophie s'excentrent pour que leurs élèves profitent de la tranquillité et soient totalement isolés pendant les deux années de leur éphébie.
L'agora devient le centre social et politique de la cité avec l'installation des institutions démocratiques sur cette place. En été de nombreux débats houleux ou amicaux se tiennent à l'ombre du portique sud et de la Stoa Poikilè, on discute politique et philosophie. Des joutes oratoires d'un autre genre se déroulent sur la Pnyx, colline sur laquelle sont votées toutes les lois athéniennes. La cité est donc le cœur de la démocratie.
Sitographie
Article issu de la page (consultée le 01 dec 2023) Démocratie Athénienne sur wikipedia.org: https://fr.wikipedia.org/wiki/D%C3%A9mocratie_ath%C3%A9nienne
Le contenu doit être mis dans un document avec l’extension .html.
A vous de jouer: Copiez l’ensemble du texte. Dans un editeur de texte: Rechercher parmi les logiciels installés: Notepad++: coller le texte. Sauvegarder dans vos Documents avec le nom athenes.html
Ouvrir à l’aide d’un navigateur: Double clic sur le document depuis l’explorateur windows, ou bien, depuis le menu fichier du navigateur: Ouvrir.. et rechercher le document.
Problèmes:
On obtient alors un document qui n’a aucune structure
De plus, avec certains navigateurs, certains caractères ne sont pas reconnus et cela peut donner le rendu suivant:
fichier texte non formaté ouvert avec un navigateur
On va résoudre certains de ces problèmes en déclarant le format d’encodage des caractères. Cette information est très importante pour le navigateur.
Au début du document html: Ajouter avec l’editeur les lignes suivantes:
<!DOCTYPE html><html><head><metacharset="utf-8"><title>page principale</title></head><body><main>Démocratie athénienne
Les origines de la démocratie athénienne
Au vie siècle av. J.-C., ...
Ajouter aussi les lignes suivantes en FIN de document:
</main></body></html>
Navigateur: Recharger la page (CTRL + r). Que remarquez vous?
Définir des éléments dans la page
Pour créer un paragraphe, le contenu devra être inséré entre une balise de début <p> et une balise de fin </p>.
Les autres balises principales sont:
Titre 1: <h1> ... </h1>
Titre 2: <h2> ... </h2>
Titre 3: <h3> ... </h3>
Bloc de citation: <blockquote> ... </blockquote>
liens: <a> ... </a>
Où les ... signifient le contenu.
Balises HTML: modifier la structure du document à l’aide des balises HTML:
ajouter la balise h1 pour le titre principal
ajouter les balises h2 pour les titres des chapitres
ajouter les balises p pour les paragraphes
ajouter les balises a pour les liens: Le lien se trouve en fin de document dans cet exemple.
Il s’agit du texte: Article issu de la page (consultée le 01 dec 2023) Démocratie Athénienne sur wikipedia.org: https://fr.wikipedia.org/wiki/D%C3%A9mocratie_ath%C3%A9nienne
Identifier l’URL de redirection (l’adresse du lien): https:/ ... dates-cle/
Identifier la cible du lien (le mot sur lequel vous devez cliquer): Démocratie Athénienne sur wikipedia.org
Remplacer ce texte par le script suivant:
Article issu de la page (consultée le 01 dec 2023) <ahref="https://fr.wikipedia.org/wiki/D%C3%A9mocratie_ath%C3%A9nienne">Démocratie Athénienne sur wikipedia.org</a>
A savoir: Dans les instructions de la balise <a>:
la balise <a> possède un attribut href, à l’intérieur même de la balise: <a href="">
l’URL se place entre les guillemets devant l’attribut href
la cible du lien (le texte à cliquer) se place entre la balise ouvrante <a> et fermante </a>
Navigateur: Recharger la page (CTRL + r). Que remarquez vous? Le lien est-ils actif lorsque l’on clique dessus?
Ajouter une image
L’ajout d’image diffère de la procédure d’un logiciel d’edition de texte comme Word ou Writer. Ici, on n’insère pas l’image elle-même, mais on indique son adresse sur le net. La syntaxe est la suivante:
<imgsrc="chemin vers l'image">
On choisira une image libre d’être diffusée, comme par exemple celle sur le site wikipedia ci-dessous:
Cliquer sur l'image pour télécharger
Cliquer sur l’image pour l’afficher seule dans une page.
Faire alors clic droit: enregister sous…
enregistrer l’image dans le même dossier que votre fichier athenes.html
Mettre alors l’image sous le paragraphe qui fait référence au Pnyx avec l’ensemble d’instructions:
<figure><imgsrc="pnyx.jpg"><figcaption>Un texte sous l'image</figcaption></figure>
Faites référence à l’auteur…
… si vous l’identifiez, ou bien la page dont est issue l’image, à l’aide d’un élément html qui suivra l’image. On peut modifier le texte de la balise figcaption.
<figcaption>Plate-forme de la Pnyx d'où parle l'orateur public. En arrière-plan, l'Acropole. (wikipedia)</figcaption>
Modifier la structure du document
Pour placer l’image à droite du pragraphe, on va utiliser un container (div) qui va englober les 2 éléments à placer côte à côte:
Placer la balise <div style="display:flex;"> avant le paragraphe:
<divstyle="display:flex"><pclass="gauche">L'agora devient le centre social ...
le cœur de la démocratie.</p>
Et fermer la balise </div> après l’objet figure:
<figcaption>Plate-forme de la Pnyx ... (wikipedia)</figcaption></figure></div>
Modifier les styles des éléments
Les instructions de style vont modifier les paramètres par défaut du navigateur pour les éléments HTML. L’idée est d’obtenir le rendu suivant pour votre page:
Commencer par copier et coller ces nouvelles règles de style fin de document, juste avant la balise de fermeture </html>, les lignes suivantes:
Modifier ensuite le style du titre principal ainsi que la position de l’image avec les manipulations suivantes:
Ajouter l’attribut de classe au titre h1 en modifiant sa balise. Remplacer <h1 par <h1 class="titre">
Ajouter l’attribut de classe au paragraphe qui traite de la partie sur le Pnyx. Ce paragraphe devrait alors se placer à gauche de l’image. Remplacer <p> par <p class="gauche">, seulement pour ce paragraphe.
La bataille de Marignan
Encodage des caracteres et header en html
Dans un fichier, les données sont écrites en binaire. Même les caractères sont exprimés sous forme numérique. Il existe plusieurs tables de correspondance lettre - chiffre. La plus ancienne est celle appelée ASCII. Mais la plus utile sera celle utf-8.
Le code ASCII définit la correspondance entre symboles et nombres jusqu’au nombre 127. Les caractères sont représentés par une série de 7 chiffres, en binaire. Les mots ont alors une longueur multiple de 7 chiffres binaires, puisque chaque lettre a une longueur fixe.
Dans un document HTML, on pourra tout de même afficher correctement ces caractères, mais il faudra utiliser une entité HTML, c’est à dire une combinaison de symboles connus par le navigateur comme par exemple: é pour la lettre é. Ou, mieux, utiliser l’encodage utf-8.
Unicode
Le répertoire Unicode se décline en utf-8, utf-16 et utf-32, qui sont de largeur variable ou fixe (pour utf32)
Le code UNICODE permet de représenter tous les caractères spécifiques aux différentes langues.
L’inconvenient des encodages à largeur fixe (utf-32) est qu’ils vont générer des fichiers de poids important (poids compté en kilo octets). Bien plus lourd que l’encodage ASCII. Alors que bien souvent, la plupart des caractères utilisés pour un document texte sont ceux de l’alphabet ASCII, avec quelques caractères spéciaux.
Code à largeur variable utf-8 et utf-16
Cet encodage utilise l’ASCII pour les caractères dont le point de code est inférieur ou égal à 127.
Chaque caractère dont le point de code est supérieur à 127 (0x7F) (caractère non ASCII) se code sur 2 à 4 octets.
La longueur du nombre binaire est alors variable. Un caractère peut nécessiter 8 bits (ascii), 16 bits, ou plus(jusqu’à 32 bits). Une information dans le code numérique va préciser cette longueur (correspond à un caractère spécial comme le Ã). Cela va permettre d’afficher tous les caractères. Cela génère un fichier dont le poids sera inférieur à l’utf-32.
Pour le système d’exploitation Windows, l’encodage par defaut est l’utf-16. MacOs utilise un encodage utf-8.
Activité: Définir le bon encodage en HTML
Utiliser le logiciel Notepad++ ou tout autre éditeur de script. Créer un nouveau fichier et commencer par l’entête suivant:
La balise <meta charset="ISO-8859-1"> va donner l’information au navigateur que l’encodage des caractères se fait en ASCII.
Ajouter alors les lignes suivantes:
<body><section><h3>La bataille de Marignan, une date restée gravée</h3><p>La bataille de Marignan (Marignano en Italie, aujourd’hui Melegnano, ville à 16 km au sud-est de Milan) eut lieu les 13 et 14 septembre 1515 et opposa le roi de France François Ier et ses alliés vénitiens aux mercenaires suisses qui défendaient le duché de Milan.</p><p>Il s'agit de la première victoire du jeune roi François Ier, acquise dès la première année de son règne. Celle-ci fit environ 16 000 morts en seize heures de combat.</p><p>François Ier, né sous le nom de François d’Angoulême le 12 septembre 1494 à Cognac et mort le 31 mars 1547 à Rambouillet, est un <ahref="https://fr.wikipedia.org/wiki/Liste_des_monarques_de_France">roi de France</a> ayant régné du 25 janvier 1515, jour de son sacre, à sa mort en 1547. Fils de <ahref="https://fr.wikipedia.org/wiki/Charles_d%27Orl%C3%A9ans_(1459-1496)"title="Charles d'Orléans (1459-1496)">Charles d'Orléans</a> et de <ahref="https://fr.wikipedia.org/wiki/Louise_de_Savoie">Louise de Savoie</a>, il appartient à la branche de Valois-Angoulême de la dynastie capétienne.</p></section></body></html>
Le contenu de la page se trouve entre les balise <body> et </body>. La balise <section> va créer un container et sera utile pour segmenter le document.
Question a: Sauvegarder le document avec le nom: marignan.html Puis ouvrir le document avec le navigateur. Que constatez-vous? Pourquoi?
Ajouter maintenant une DEUXIEME section avec la partie suivante: (à placer avant la balise de fermeture </body>:
<section><h3>La bataille de Marignan, une date restée gravée</h3><p>La bataille de Marignan (Marignano en Italie, aujourd’hui Melegnano, ville à 16 km au sud-est de Milan) eut lieu les 13 et 14 septembre 1515 et opposa le roi de France François Ier et ses alliés vénitiens aux mercenaires suisses qui défendaient le duché de Milan.</p><p>Il s'agit de la première victoire du jeune roi François Ier, acquise dès la première année de son règne. Celle-ci fit environ 16 000 morts en seize heures de combat.</p><p>François Ier, né sous le nom de François d’Angoulême le 12 septembre 1494 à Cognac et mort le 31 mars 1547 à Rambouillet, est un <ahref="https://fr.wikipedia.org/wiki/Liste_des_monarques_de_France"title="Liste des monarques de France">roi de France</a> ayant régné du 25 janvier 1515, jour de son sacre, à sa mort en 1547. Fils de <ahref="https://fr.wikipedia.org/wiki/Charles_d%27Orl%C3%A9ans_(1459-1496)">Charles d'Orléans</a> et de <ahref="https://fr.wikipedia.org/wiki/Louise_de_Savoie">Louise de Savoie</a>, il appartient à la branche de Valois-Angoulême de la dynastie capétienne.</p></section>
Question b: Recharger le document dans le navigateur. Que constatez-vous? Pourquoi?
Vous allez maintenant modifier l’information sur l’encodage en remplaçant la balise <meta charset="ISO-8859-1"> par balise <meta charset="utf-8">. Revenir sur la première version du texte (celui avec les accents é, à, …).
Question c: Recharger le document dans le navigateur. Que constatez-vous? Pourquoi?
introduction au CSS
Vous avez découvert le langage HTML (Hypertext Markup Langage) dans le TP précédent. Celui-ci gère la structure ET le contenu du document. La mise en forme dépend alors de votre navigateur, à partir des règles de mise en page standart qu’il va appliquer.
Mais pour maitriser et personnaliser cette mise en forme, il faut utiliser un langage prévu pour gérer les styles. C’est le langage CSS (Cascading Style Sheet).
Les instructions de style se mettent entre les balises <style>. Ces balises seront placées après la fermeture </head> et avant l’ouverture du contenu <body>
Pour approfondir, suivre le tutoriel à la page developper.mozilla sur le CSS niveau débutant.
Hierarchie des éléments html, bordures
Dans le document marignan.html, les éléments HTML ont une certaine hierarchie: Les balises <h3> et <p> sont à l’intérieur de la balise <section>. Si on veut encadrer le contenu, il faudra appliquer les règles à l’élément section:
section{...}
Les règles peuvent permettre de
fixer la largeur
mettre une marge entre les éléments
mettre une couleur de fond
dessiner une bordure
Suivre maintenant le tutoriel developper.mozilla pour voir un exemple d’application de ces règles.
travaux pratiques: écrire les règles de style CSS qui vont permettre d’obtenir la mise en forme suivante:
Question e: faire un tableau avec 3 colonnes: nom de la propriété, effet de style, exemple de valeur. Mettre dans ce tableau au moins 3 propriétés prévues pour styliser le texte, et 3 propriétés pour styliser le container de ce texte.
Positionnement des éléments
Les éléments section se placent naturellement l’un sous l’autre. Ce qui donne, pour la page avec 2 éléments section:
Pour modifier cette mise en page, et mettre les 2 éléments côte à côte, il faut appliquer la règle de positionnement à l’élément PARENT des 2 éléments section. Ici, cet élément parent, c’est body.
La règle à appliquer, c’est:
display:flex;
Ajouter cette règle CSS pour obtenir la disposition suivante:
Question f:: Ecrire la règle complète que vous avez utilisée.
Vous savez maintenant positionner les éléments dans le flux vertical, horizontal, mettre une image dans un container sans que celle-ci déborde, et utiliser des règles CSS pour personnaliser les styles. Vous pouvez peut-être, s’il vous reste du temps, revenir sur le TP précédent et personnaliser l’affichage de votre page…
mon film prefere v1
Créer une page web sur votre film préféré
Le but de cet exercice est de réaliser une page HTML de présentation de votre film préféré. Cette page sera simple. On pourra piocher les informations de votre film sur des bases de données en ligne de films telles que IMDb, AlloCiné, Wikipédia…
L’objectif est de réaliser une page qui pourrait présenter les informations comme ceci:
Mise en place de l’environnement de travail de notre site web
Dans un premier temps :
dans votre répertoire personnel: créez un dossier appelé web, ou utlisez votre précédent dossier (celui contenant vos autres pages web, réalisées lors des précédentes séances).
Attention, on prendra soin de ne pas mettre d’espaces et d’accents dans notre arborescence de fichiers et dossiers.
Dans le dossier web, créez un nouveau dossier, que vous appelerez pages
Dans le dossier pages, créez un nouveau fichier à l’aide de l’editeur Notepad++. Copiez-collez les lignes suivantes:
<!DOCTYPE html><html><head><metacharset="utf-8"><title>page principale</title></head><style>/* placer ici vos déclarations CSS*/</style><body><!-- le contenu de votre page web.
Ceci est un commentaire et peut être effacé.
--></body></html>
Sauvegardez le en l’appelant page1.html
Dans le dossier pages, créer un nouveau dossier que vous appelerez images. Placez dans ce dossier les images du film que vous souhaitez afficher dans votre page.
Ouvrir le fichier à l’aide d’un navigateur (Mozilla, Edge, …). Rafraichir la page à chaque modification.
Contenu du fichier
Rappelez-vous: le contenu de votre document se place entre les balises <body> et </body>. A chaque modification, vous devrez Enregistrer votre document pour que ces modifications soient prises en compte.
Le document contiendra les éléments suivants:
Ce document a été réalisé par VOTRE NOM ET PRENOM
TITRE DU FILM
Informations générales:
Année de Sortie
Réalisateur
Acteurs Principaux
Genre
Résumé
Bande-Annonce du Film
Sources des informations et médias
Méthode:
Ces éléments peuvent être des titres (h1), des sous-titres (h2), … Voir le TP de découverte du HTML.
On pourra aussi mettre en évidence, avec la balise <strong>, les différents items de la partie Informations générales.
Les éléments de liste peuvent être placés les uns sous les autres, organisés (liste à puce) à l’aide du système d’instructions suivant: (balises ul et li)
<ul><li>Année de sortie: </li><li>Réalisateur: </h1><li>...</li></ul>
Modifiez le texte Ce document a été réalisé par VOTRE NOM ET PRENOM et TITRE DU FILM
Enregistrez votre travail puis faire F5 dans votre navigateur pour rafraîchir la page. Admirez votre premier travail.
Compléter les informations
Des paragraphes
À l’aide des sites web du début de page, renseignez les différentes informations de la page.
Méthode: Utilisez les balises <p> ... </p> pour placer des informations dans un paragraphe (par exemple pour le résumé)
Créer des liens hypertextes
On l’a vu précédemment, les liens hypertextes sont la base du Web. Voyons comment réaliser ces liens avec du HTML. Un lien permet simplement de se déplacer vers une autre page HTML.
<a> désigne une ancre, c’est-à-dire un lien vers une cible de destination. Cette balise entoure généralement un mot (une image, un paragraphe, un titre, …) qui devient le texte ‘support du lien’ hypertexte.
Dans la partie Sources des informations et médias, ajouter le ou les site·s où vous avez pris vos informations et l’affiche en créant un lien vers le ou les site·s en question.
Ajouter une image
(1) Depuis un site web, télécharger le fichier image du film en faisant un clic-droit dessus Enregistrer l’image sous… Enregistrez ce fichier dans le dossier images crée précédemment.
(2) Nommez cette image affiche.jpg, ou affiche.png ou encore affiche.webp selon le format initial du fichier image.
Pour ajouter une image dans une page HTML, il faut utiliser la balise
<imgsrc="image/affiche.png"/>
chemin vers l’image est le chemin à fournir à partir du fichier HTML:
si le fichier affiche.png est enregistré dans le dossier pages, à côté de page1.html, on met la ligne de code suivante : <img src="affiche.png"/>
Si l’image se trouve dans le dossier images, et qu’elle s’appelle affiche.png, le chemin est images/affiche.png
(3) Ajoutez l’affiche à votre page web en ajoutant la balise HTML adéquate.
Si votre affiche est trop grande, on peut demander au navigateur de réduire sa largeur en pixels (propriété CSS width:300px;)
(4) Ajouter une déclaration CSS pour les éléments img de la manière suivante:
Entre les balise <style> ... </style> du debut du document, ajouter la déclaration:
img{width:300px;}
Lien vers une bande d’annonces
Nous allons ajouter une image, qui, lorsqu’elle est cliquée, envoie vers la page de la bande d’anonce.
(1) Rechercher le lien vers la bande d’annonce (Youtube)
(2) Télécharger l’image ci-dessous, player.png, ou bien concevoir votre propre image à partir de celle-ci
Et si je veux mettre un peu de couleurs ? Le style d’un document est apporté par le langage CSS
Ok, le rendu précédent n’est pas très fun, c’est le rendu par défaut des différentes balises ; on va donc ajouter des instructions de styles à notre page afin de la personnaliser à notre goût.
Voici un exemple: copiez le code ci-dessous. Placez le à la fermeture de la balise </head> et avant l’ouverture par la balise <body>
Vous avez terminé et c’est validé par votre enseignant ? Vous pouvez :
améliorer le style à l’aide de nouvelles règles CSS
rajouter des pages à votre site (autre film, 2e volet du film…)
Vous trouverez de nombreuses références sur les styles sur Internet mais le plus simple sera d’utiliser cette page, ou bien celui-ci très complet: MDN Mozilla
mon film prefere v2
Créer une page web sur votre film préféré
Le but de cet exercice est de réaliser une page HTML de présentation de votre film préféré. Cette page sera simple. On pourra piocher les informations de votre film sur des bases de données en ligne de films telles que IMDb, AlloCiné, Wikipédia…
L’objectif est de réaliser une page qui pourrait présenter les informations comme ceci:
Mise en place de l’environnement de travail de notre site web
Dans un premier temps :
dans votre répertoire personnel: créez un dossier appelé web, ou utlisez votre précédent dossier (celui contenant vos autres pages web, réalisées lors des précédentes séances).
Attention, on prendra soin de ne pas mettre d’espaces et d’accents dans notre arborescence de fichiers et dossiers.
Dans le dossier web, créez un nouveau dossier, que vous appelerez pages
Dans le dossier pages, créez un nouveau fichier à l’aide de l’editeur Notepad++. Copiez-collez les lignes suivantes:
<!DOCTYPE html><html><head><metacharset="utf-8"><title>page principale</title></head><style>/* placer ici vos déclarations CSS*/</style><body><!-- le contenu de votre page web.
Ceci est un commentaire et peut être effacé.
--></body></html>
Sauvegardez le en l’appelant page1.html
Dans le dossier pages, créer un nouveau dossier que vous appelerez images. Placez dans ce dossier les images du film que vous souhaitez afficher dans votre page.
Ouvrir le fichier à l’aide d’un navigateur (Mozilla, Edge, …). Rafraichir la page à chaque modification.
Contenu du fichier
Rappelez-vous: le contenu de votre document se place entre les balises <body> et </body>. A chaque modification, vous devrez Enregistrer votre document pour que ces modifications soient prises en compte.
Le document contiendra les éléments suivants:
Ce document a été réalisé par VOTRE NOM ET PRENOM
TITRE DU FILM
Informations générales:
Année de Sortie
Réalisateur
Acteurs Principaux
Genre
Résumé
Bande-Annonce du Film
Sources des informations et médias
Méthode:
Ces éléments peuvent être des titres (h1), des sous-titres (h2), … Voir le TP de découverte du HTML.
On pourra aussi mettre en évidence, avec la balise <strong>, les différents items de la partie Informations générales.
Les éléments de liste peuvent être placés les uns sous les autres, organisés (liste à puce) à l’aide du système d’instructions suivant: (balises ul et li)
<ul><li>Année de sortie: </li><li>Réalisateur: </h1><li>...</li></ul>
Modifiez le texte Ce document a été réalisé par VOTRE NOM ET PRENOM et TITRE DU FILM
Enregistrez votre travail puis faire F5 dans votre navigateur pour rafraîchir la page. Admirez votre premier travail.
Compléter les informations
Des paragraphes
À l’aide des sites web du début de page, renseignez les différentes informations de la page.
Méthode: Utilisez les balises <p> ... </p> pour placer des informations dans un paragraphe (par exemple pour le résumé)
Créer des liens hypertextes
On l’a vu précédemment, les liens hypertextes sont la base du Web. Voyons comment réaliser ces liens avec du HTML. Un lien permet simplement de se déplacer vers une autre page HTML.
<a> désigne une ancre, c’est-à-dire un lien vers une cible de destination. Cette balise entoure généralement un mot (une image, un paragraphe, un titre, …) qui devient le texte ‘support du lien’ hypertexte.
Dans la partie Sources des informations et médias, ajouter le ou les site·s où vous avez pris vos informations et l’affiche en créant un lien vers le ou les site·s en question.
Ajouter une image
(1) Depuis un site web, télécharger le fichier image du film en faisant un clic-droit dessus Enregistrer l’image sous… Enregistrez ce fichier dans le dossier images crée précédemment.
(2) Nommez cette image affiche.jpg, ou affiche.png ou encore affiche.webp selon le format initial du fichier image.
Pour ajouter une image dans une page HTML, il faut utiliser la balise
<imgsrc="image/affiche.png"/>
chemin vers l’image est le chemin à fournir à partir du fichier HTML:
si le fichier affiche.png est enregistré dans le dossier pages, à côté de page1.html, on met la ligne de code suivante : <img src="affiche.png"/>
Si l’image se trouve dans le dossier images, et qu’elle s’appelle affiche.png, le chemin est images/affiche.png
(3) Ajoutez l’affiche à votre page web en ajoutant la balise HTML adéquate.
Si votre affiche est trop grande, on peut demander au navigateur de réduire sa largeur en pixels (propriété CSS width:300px;)
(4) Ajouter une déclaration CSS pour les éléments img de la manière suivante:
Entre les balise <style> ... </style> du debut du document, ajouter la déclaration:
img{width:300px;}
Lien vers une bande d’annonces
Nous allons ajouter une image, qui, lorsqu’elle est cliquée, envoie vers la page de la bande d’anonce.
(1) Rechercher le lien vers la bande d’annonce (Youtube)
(2) Télécharger l’image ci-dessous, player.png, ou bien concevoir votre propre image à partir de celle-ci
Et si je veux mettre un peu de couleurs ? Le style d’un document est apporté par le langage CSS
Ok, le rendu précédent n’est pas très fun, c’est le rendu par défaut des différentes balises ; on va donc ajouter des instructions de styles à notre page afin de la personnaliser à notre goût.
Voici un exemple: copiez le code ci-dessous. Placez le à la fermeture de la balise </head> et avant l’ouverture par la balise <body>
Associez votre page à celles déjà réalisées (TP1, TP2), afin de créer un site Web complet.
Organisez votre code et vos fichiers et sous-dossiers du projet.
Essayez autant que possible d’avoir une présentation homogène pour toutes les pages de votre site.
Utiliser une feuille de style pour rassembler toutes les déclarations CSS du site.
Ajouter une page pour personnaliser encore plus votre site (vous aimez les voyages, la lecture, la peinture, les jeux videos…), partagez vos goûts ou vos connaissances.
Vous trouverez de nombreuses références sur les styles sur Internet mais le plus simple sera d’utiliser cette page, ou bien celui-ci très complet: MDN Mozilla
questionnaire
Formulaires
La réalisation d’une enquête de terrain consiste à interroger les usagers au moyen d’un questionnaire.
But et règlementation
Lors de la confection du questionnaire, posez-vous au minimum les questions suivantes:
quel est le but du questionnaire?
quel est le public visé?
la collecte des informations personnelles est-elle anonyme?
si celle-ci n’est pas anonyme, que prevoyez-vous en regard du RGPD?
la collecte des informations, est-elle simple?
Questionnaire à destination des parents
Nous prendrons comme exemple le Questionnaire suivant, dont le but est d’établir un profil de la famille et des enfants scolarisés dans une école élémentaire. Ce questionnaire est adressé aux parents:
Combien d’enfants avez vous?
L’enfant scolarisé dans notre école, s’agit-il d’une fille/d’un garçon?
Bénéficie t-il (elle) d’un dispositif particulier (PAP, PAI, …)?
Fréquente t-il (elle) l’accueil périscolaire du matin?
Vous allez adapter ce questionnaire pour le publier en ligne.
Ce questionnaire est anonyme; la plupart des questions sont de type Question à Choix Multiple, n’autorisant qu’une seule réponse.
Ce type de questions est à privilégier pour en faciliter l’analyse.
Framaforms
Les données relatives aux élèves ou à leurs parents sont des données sensibles qu’il faut protéger. Même si cela peut paraitre tentant d’utiliser les outils de formulaires américains tels que Microsoft et Google, il faut les éviter d’après la CNIL, car non respectueuses du RGPD en raison du «privacy shield» américain.
Dans ce TP, vous allez devoir créer un compte sur framaforms, une association française qui respecte le RGPD qui s’engage à ne pas vendre vos données ni celles de vos utilisateurs.
Une fois le compte créé, aller dans l’editeur et commencer à concevoir le formulaire.
Mettre un titre et un commentaire à partir des informations suivantes:
Titre du formulaire:Questionnaire à destination des parents
Description:Madame, Monsieur, chers parents,
Dans le cadre de l’auto-évaluation de notre école, nous vous proposons une enquête afin d’établir un profil et de répondre à vos besoins.
Votre participation à l’enquête est essentielle. Elle est libre et anonyme. Il vous suffit d’indiquer ce que vous pensez des propositions qui suivent.
Nous vous remercions à l’avance de votre participation.
L’équipe pédagogique
Accès public aux résultats: Choisir Non.
En bas de page: Cliquer sur Enregistrer
Ajouter votre première liste à puces: haut de page: Formulaire
Dans l’onglet Options, modifier les valeurs des boutons.
Pour être plus lisible, le champs de réponses peut être placé sur la même ligne que la question.
La question suivante pose un problème pour l’analyse des résultats: Votre enfant bénéficie-t-il d’un dispositif?. Le choix Non n’apparait pas.
Il faudra d’abord placer une 1ere question: Votre enfant bénéficie-t-il d’un dispositif d’accompagnement?: OUI / NON
Puis la question demandant le type de dispositif: (PAI, PAP, UPE2A, ULIS)?
Enfin, il faudra lier ces 2 questions: la 2e question ne sera proposée qu’à condition que la réponse précédente est OUI. Cela demande d’ajouter un champ conditionnel
La reponse OUI à la première question entraine l’affichage de la 2e:
choix de la question 1
choix de la question 2
Les questions suivantes sont regroupées dans un même tableau. Pour chaque tableau, on les regoupe dans le même paragraphe du formulaire.
Choisir: groupe de champs
Puis ajouter les questions dans ce groupe de champs.
Vous pouvez alors partager ce formulaire grâce à son adresse. Voir le bouton partager depuis le tableau de bord.
Liens
Questionnaires préparatoires à l’évaluation d’école (documents nationaux) disponibles ci-dessous et sur l’ENT : ac-Lille
importer un fichier de reponses en format csv, analyse et representations graphiques
Sous-sections de utiliser un tableur
tableau de notes
Tableau de notes
Tableurs
Les tableurs sont des logiciels de présentation et de traitement de données.
les suites Microsoft Office et LibreOffice proposent les mêmes logiciels, mais les formats de fichiers différent.
Logiciel
LibreOffice
Extension
Microsoft
Extension
Traitement de textes
Writer
odt
Word
docx
Tableur
Calc
ods
Excel
xlsx
Présentations
Impress
odp
PowerPoint
pptx
Les fonctionnalités de ces logiciels sont identiques. Pour les tableurs, la page est un tableau de cellules, repérées par leurs coordonnées (A1, A2, …). La mise en forme du tableau demande une certaine maitrise des différents curseurs.
Les curseurs pour manipuler les cellules
Il existe 3 sortes de curseur dans la page: “main”, “croix blanche”, “croix noire”. C’est en faisant glisser celui-ci dans la cellule que l’on peut passer d’un curseur à l’autre.
Main: déplacer une cellule
Ouvrir le logiciel Excel (document vierge). Ecrire Le nom de l’école.
Choisir alors le curseur “main” et déplacer la cellule dans A1.
Croix blanche: sélection étendue
La croix blanche permet de selectionner plusieurs cellules, ou de selectionner une plage de cellule (utile pour les formules de calcul)
Glisser le curseur au centre de la cellule. Lorsque l’on obtient une croix blanche, cliquer-glisser sur plusieurs colonnes pour faire une sélection étendue.
On peut alors fusionner les cellules: clic droit > format de cellule
Cocher la case “fusionner (merge)”. Puis aligner le texte au centre.
Compléter alors le tableau selon l’image suivante:
Croix noire: reproduire une mise en forme
Ecrire pour nom du premier élève: Elève 1.
Glisser le curseur dans le coin inférieur droit de la cellule pour obtenir une croix noire.
cliquer-glisser le long de la colonne, sur 3 lignes.
Le tableur adapte alors le contenu. Ici, en numérotant les élèves.
Formules de calcul
Le traitement des données peut se faire à l’aide de fonctions ou bien de formules mathématiques.
Avant de commencer, compléter le tableau avec les notes des élèves.
Fonctions
Le nom des fonctions peut différer selon les logiciels tableurs utilisés. Il peut être prudent d’utiliser le concepteur de formule (bouton fx).
Une fois que vous avez saisi = ainsi que les premières lettres de la fonction, le concepteur de formule va vous proposer un choix parmi les fonctions existantes.
Pour calculer la moyenne de la classe obtenues pour les élèves au devoir 1:
dans une cellule de la colonne B (devoir 1), commencer par écrire =
Puis la fonction MOYENNE(
Ecrire le paramètre entre parenthèses: il faut placer les coordonnées de la plage de valeurs. Avec l’outil de sélection étendue (croix blanche), sélectionner toutes les cellules des devoir 1: B6:B8. Fermer la parenthèse.
Modifier le format de cellule pour afficher une valeur arrondie (1 ou 2 chiffres après la virgule): clic droit > Format de cellule
On devrait obtenir maintenant le tableau suivant:
Reproduire la mise en forme dans les cellules voisines: croix noire dans la cellule B9 puis cliquer-glisser jusqu’à devoir 4.
C’est là l’une des fonctions magiques du logiciel. Observez les paramètres de chacune des fonctions reproduites. Pour le devoir 2, vous devriez voir =MOYENNE(C6:C8). Le logiciel a adapté la mise en forme, dans la nouvelle colonne, à partir de celle adjacente!
Ecrire une formule
La formule non coefficientée, pour l’élève 1 s’écrira:
$$= (B6/B5+C6/C5+D6/D5+E6/E5) * 20 / 4$$
Il s’agit de la somme de ses notes, divisée par la somme de la ligne “note sur:” , Le tout, multiplié par 20.
Pour calculer la moyenne de l’élève 1, après ses 4 devoirs: Dans quelle cellule va t-on placer la formule?
Saisir cette formule dans la cellule la plus adaptée. Puis modifier le format de cellule pour arrondir à 2 chiffres après la virgule.
On souhaite reproduire la mise en forme afin de calculer la moyenne pour les autres élèves. Comment va-t-on s’y prendre?
Reproduire la mise en forme du calcul de moyenne pour chaque élève. Les résultats vous paraissent-ils cohérents? D’où cela peut-il provenir?
Nous allons corriger ce problème dans le paragraphe suivant…
Références relatives ou absolues
Le problème précédent vient de la manière avec laquelle nous avons écrit les coordonnées de cellules. Le calcul doit être reproduit pour chaque élève, mais avec des coordonnées pour les valeurs note sur: qui doivent rester fixes. Pour cela, à la place d’écrire $= (B6/B5+C6/C5...$ dans la formule de calcul pour l’élève 1, nous allons écrire: = (B6/B$5+C6/C$5...
Cela ne change rien au calcul de la moyenne de l’élève 1. Par contre, si vous faites une reproduction de la mise en forme pour les autres élèves, leur moyenne est cette fois-ci correctement calculée: La copie de la formule ne modifie pas la reference de cellule de la ligne 5.
Finir le tableau
Il vous reste maintenant:
à tenir compte des coefficients pour chaque matière. Cela va vous obliger à modifier la formule de calcul de moyenne par élève:
Le prix Nobel est une récompense de portée internationale. Remis pour la première fois en 1901, les prix sont décernés chaque année à des personnes « ayant apporté le plus grand bénéfice à l’humanité », par leurs inventions, découvertes et améliorations dans différents domaines de la connaissance, par l’œuvre littéraire la plus impressionnante, ou par leur travail en faveur de la paix, suivant ainsi les derniers vœux d’Alfred Nobel, inventeur de la dynamite.
L’année 2023 a vu une féminisation des lauréats au prix Nobel. Mais depuis sa création, le nombre de femmes primées est-il comparable aux hommes? Faisons le bilan.
Prix Nobel : une féminisation à tout petit pas - TV5 Monde
Narges Mohammadi, Claudia Goldin, Anne L’Huillier, Katalin Karikó. Quatre noms de femmes s’ajoutent en 2023 à la liste des “Nobélisé-es”. Un seul en 2024, Han Kang, prix nobel de littérature.
Fichier de données
Selon la version Excel installée:
méthode 1: avec Excel jusqu’à la version 16 (2019), ou bien LibreOffice Calc:
Fichier: Importer le fichier de données nobels.csv.
méthode 2: Excel version plus récente
Données: Obtenir des données, puis choisir “à partir d’un fichier”, “fichier text ou csv”, choisir le fichier nobels.csv.
Dans les 2 cas (méthode 1 ou 2): Bien sélectionner:
séparateur par point virgule
Origine du fichier: unicode utf-8 afin de bien gérer les caractères avec accents.
Puis Enregistrer le fichier au format xls (ou xlsx) dans le même répertoire.
Maintenant que nous sommes sur un fichier en format tableur, nous pouvons utiliser les fonctionnalités avancées de ce type de logiciel.
Rechercher et remplacer: (facultatif)
Commencer par franciser le fichier en utilisant les noms des descripteurs et des prix en français (Physics
-> Physique…). Pour cela utiliser la fonction Rechercher et
Remplacer(Menu Edition> Rechercher et Remplacer)
Filtrage des données
Selectionner toutes les colonnes du tableau
Cliquer sur l’icône en forme d’entonnoir dans le menu du haut. Vous pouvez maintenant cliquer sur les petites flèches à côté des noms des descripteurs pour filtrer les données (ne sélectionner que certaines valeurs), les trier par ordre croissant, ou décroissant.
Vous obtenez alors une VUE à partir de votre TABLE. C’est à dire un extrait de la table.
Qu 2a. Quand a été décerné le premier prix Nobel de Littérature? Et d’économie? Combien de lauréats ont reçu un prix Nobel cette année?
Qu 2b. Combien de femmes ont reçu un prix Nobel? Et d’hommes?
Qu 2c. Quelle est la discipline dans laquelle les femmes sont les plus représentées? Le moins représentées?
Qu 2d. Bilan: Quelle est la différence entre FILTRER et TRIER des données? Expliquer le rôle de chacune de ces fonctions en utilisant l’exemple de la Qu 2a. Rechercher le nom des instructions correspondante en langage SQL sur une base de données: Lien 1: order by, Lien 2: where
Nouveau tableau statistique
Nous allons maintenant créer un nouveau tableau pour rassembler des statistiques sur le genre des prix Nobel.
Rappelez-vous que les formules commencent toujours par un signe =.
Pour référencer une cellule on utilise son adresse sous la forme
ColonneLigne. Exemple: D2 pour la cellule de la colonne D, ligne 2.
On peut référencer une plage de cellule.
Exemple: D2:D10 pour les cellules D2 à D10 de la feuille.
Dans une partie libre de la feuille, créer le tableau suivant:
Nombre de femmes prix nobel Chimie
Dans la cellule Chimie -> femme, écrire = puis NB.SI.ENS(
La fonction NB.SI.ENS applique des critères aux cellules de plusieurs plages et compte le nombre de fois où tous les critères sont remplis.
Pour chacune des cases des colonnes femme et homme, saisir les formules qui donnent les nombre de femmes et d’hommes pour chaque catégorie de prix Nobel. Utiliser la fonction =NB.SI.ENS()
Totaux
Dans les colonnes totaux (dernière colonne et dernière ligne), appliquer la fonction SOMME pour ajouter les valeurs sur une même ligne, ou sur une même colonne. support microsoft
Il est aussi possible d’utiliser une formule utilisant des opérateurs mathématiques (+, -, /, *) sur les cellules: = A1 + A2 par exemple, pour additionner les valeurs des cellules A1 et A2.
Qu 3a. Compléter les valeurs du tableau dans la feuille de reponse.
Qu 3b. Calculer dans une cellule de la feuille Excel, la proportion de femmes parmi les nobélisés (pourcentage). Donner le résultat, ainsi que la formule utilisée.
Graphique
Sélectionner les données calculées du nouveau tableau de statistiques pour créer un histogramme résumant les données.
On peut s’aider du tutoriel suivant pour l’affichage d’un histogramme.
Excel - 1 Basique - Cours Graphique
exemple d'histogramme réalisé sur des valeurs fictives
Base de données
Telecharger la base de données sous format SQL: nobels.sql.
Ouvrir dans un nouvel onglet le gestionnaire de bases de données sqliteonline.com.
Depuis le menu du logiciel, faire (+) dans le coin gauche et import. Importer alors le fichier SQL.
Tester alors dans l’editeur les commandes SQL correspondant aux requêtes que vous avez réalisées depuis le tableur.
Lors de la seance précédente, vous avez réalisé un questionnaire en ligne. L’interface de framaforms permet de visualiser les réponses, et d’établir des statistiques.
Mais, les réponses étant accessibles dans un format standard, le fichier de données peut également être ouvert avec un logiciel tableur.
Soumission et import des résultats du questionnaire
A l’aide du lien de partage sur votre tableau de bord sur framaforms.org, répondez à votre questionnaire.
Répéter l’opération au moins 2 fois. Puis, depuis votre tableau de bord, choisissez le téléchargement en format csv.
Choisir virgule (,) comme séparateur.
Dans Composants d’export inclus, choisir les informations à importer. Ne pas choisir celles relatives à l’identité des parents questionnés (formulaire anonyme).
Télécharger votre fichier.
Question a: Quelle est l’extension du fichier? Avec quel logiciel (editeur texte) peut on ouvrir et visualiser les données? Donner au moins 2 exemples à partir des logiciels installés sur votre ordinateur.
Question b: Comment sont organisées les données dans le fichier? Décrire le format des données.
Pour la suite de la séance, nous allons prendre le fichier suivant, resultats.csv pour analyse.
Vous allez réaliser un premier travail de mise en forme des données avant leur représentation graphique.
Mise en forme des données sous Excel
Télécharger le ficher, resultats.csv, et l’ouvrir avec Excel (ou bien LibreOffice Calc) comme vu dans le TP sur le format des données.
Enregistrer le fichier au format xls dans le même répertoire. Attention, Sans cette manipulation, csv -> xls, vous risquez de perdre vos travaux sur ce fichier.
Maintenant que nous sommes sur un fichier tableur d’extension xls, nous pouvons utiliser les fonctionnalités avancées de ce type de logiciel.
Question c: Combien de réponses au formulaire sont présentées dans le tableau?
Question d: Combien de questions comporte le formulaire?
Utiliser la fonction nb.si
Pour compter le nombre de “Oui” dans une colonne, utiliser la fonction NB.SI
Pour compter le nombre d’élèves qui fréquentent la cantine: Ecrire sous la colonne Cantine:
$$=NB.SI(plagedonnees;"Oui")$$
selection de la plage de données (en pointillés bleus) après avoir écrit =NB.SI(
Ainsi, pour savoir combien d’élèves de “CP” déjeunent à la cantine, il y aura 2 couples plage critère <-> critère:
La première plage critère: sélection de la classe. B1:B50 si la colonne B correspond à la classe. Et que 50 lignes sont renseignées.
Le premier critère: “CP”
La deuxième plage critère: C1:C50
Le deuxième critère: “Oui”
Question f: Quelle est alors la formule utilisée dans la cellule du tableur?
Partie 2: Etude statistique
Tableau statistique à 2 entrées
Cette deuxième partie demande une nouvelle présentation des données.
Vous allez créer 2 nouvelles tables à partir des résultats bruts:
Une table donnant les effectifs cantine, suivi périscolaire:
Une table donnant une information sur la qualité d’accueil
Les valeurs sont indicatives. Celles affichées dans chacune de vos tables doivent être calculées à partir du fichier .csv fourni, à l’aide des formules nb.si et nb.si.ens vues dans la partie 1.
Tableur Excel
Construire une formule de calcul de moyenne Fonction somme Pour programmer la fonction SOMME sur les valeurs d’une colonne du tableau
Voici un lien vers le tuto de microsoft office.
cliquer dans la cellule juste sous la dernière valeur de la colonne. Ecrire debut de la formule (bien commencer la ligne par le signe =): = SOMME( puis faire une sélection étendue de toutes les valeurs de la colonne. (voir image ci-dessous) Valider avec la touche Entrer Compter le nombre de cellules Pour compter le nombre de valeurs dans le tableau, utiliser la fonction NOMBRE
Tracé d’un histogramme avec Excel Un histogramme donne une représentation d’un tableau avec des effectifs, de manière très visuelle. Cela facilité grandement l’interprétation.
Dans une feuille du tableur Excel:
Placer dans une première ligne les etiquettes des colonnes (par exemple, renseigner le nom des matières) Placer juste au dessous les effectifs correspondant (par exemple, la matière préférée) Selectionner ensuite l’emplacement des données (ne pas prendre la première colonne, qui constitue le titre).
Recherche de corrélations Principe La recherche de correlations entre valeur d’un tableau consiste à identifier des colonnes qui semblent être interdépendantes.
On doit commencer par rassembler les données dans une même table, où les réponses d’une même personne sont rassemblées dans une même ligne.
data.gouv Le site data.gouv.fr est la plateforme des données publiques françaises.
Nous allons consulter les données du Répertoire National des Élus (RNE). Celui-ci a pour finalité le suivi des titulaires d’un mandat électoral. Il est renseigné et tenu à jour par les préfectures et les services du ministère de l’intérieur.
Rendez vous à la page de consultation du RNE.
Utilisation de la base de données Ouvrir la base de données Aller sur la page Exoplanet.eu Pour consulter la base de données de toutes les planetes observées, cliquer sur Tous les catalogues.
accès à la base de données
Sous-sections de analyser
somme et moyenne sur Excel
Tableur Excel
Construire une formule de calcul de moyenne
Fonction somme
Pour programmer la fonction SOMME sur les valeurs d’une colonne du tableau
Ecrire debut de la formule (bien commencer la ligne par le signe =): = NOMBRE(
puis faire une sélection étendue de toutes les valeurs de la colonne.
Valider avec la touche Entrer
Calculer la moyenne
La moyenne des valeurs se calcule en divisant le résultat de SOMME par celui de NOMBRE.
Supposons que la somme se trouve dans la cellule D18, et le nombre dans D19, alors il faudra calculer avec la formule:
=D18/D19
Placer cette formule dans une cellule libre de la feuille de calcul, si possible sous les autres valeurs
Cette formule est DYNAMIQUE: si vous modifiez une valeur dans le tableau, tout est recalculé. Vous avez créé une tâche AUTOMATISEE.
tracé d'un histogramme
Tracé d’un histogramme avec Excel
Un histogramme donne une représentation d’un tableau avec des effectifs, de manière très visuelle. Cela facilité grandement l’interprétation.
Dans une feuille du tableur Excel:
Placer dans une première ligne les etiquettes des colonnes (par exemple, renseigner le nom des matières)
Placer juste au dessous les effectifs correspondant (par exemple, la matière préférée)
Selectionner ensuite l’emplacement des données (ne pas prendre la première colonne, qui constitue le titre).
Dans le menu INSERTION (1), choisir HISTOGRAMME 2D(2). Prendre le premier histogramme proposé (en haut à gauche).
Vous devriez obtenir un diagramme de frequence en batons (un histogramme).
recherche de correlations
Recherche de corrélations
Principe
La recherche de correlations entre valeur d’un tableau consiste à identifier des colonnes qui semblent être interdépendantes.
On doit commencer par rassembler les données dans une même table, où les réponses d’une même personne sont rassemblées dans une même ligne.
Puis on fait des hypothèses sur ce qui pourrait montrer une interdépendance:
Exemple: il y a peut être un lien entre la durée du trajet scolaire, et l’avance avant le début des cours.
Contre exemple: il y a peu de chances de trouver une corrélation entre l’âge et la durée du trajet scolaire.
On selectionne alors les colonnes de la table qui sont probablement corrélées. On les porte comme axes X et Y dans un graphique. Puis on place les points pour chaque élève:
La corrélation peut montrer un regroupement de points
source: appendre le machine learning en une semaine, G. Saint-Cirgue
Cela peut être aussi un alignement sur une droite, ou une courbe.
source: appendre le machine learning en une semaine, G. Saint-Cirgue
En pratique
A l’aide du logiciel Excel:
importer les données à partir des fonctionnalités du logiciel (faites-vous aider par le professeur).
(1): selectionner les 2 colonnes de données. Celles-ci doivent être côte à côte dans le tableau, sinon, déplacer les colonnes.
(2): menu INSERTION
(3): choisir graphique > nuage de points
Analyser et conclure
matchs OM Nice
Matchs de Football Nice - Marseille
Le fichier suivant rescence tous les matchs de football de Ligue 1 depuis 2002.
Il s’agit d’un document tenu à jour sur le site L’Equipe.
Les fichier à télecharger:
Vous aurez besoin pour mener à bien ce travail pratique de revoir:
les calculs avec un logiciel tableur:
TP Excel
* les sommes conditionnelles:
TP Excel
Comprendre les descripteurs du tableau
1. Noter sur la fiche reponse le nom de ces descripteurs
2. Ecrire la plage des cellules contenant des valeurs pour chacun de ces descripteurs, sous la forme cellule depart : cellule arrivée
Exemple : Les valeurs du descripteur Ligue sont sur la plage A2:A7221
3. Comment peut-on savoir, en lisant le tableau, quelle est l’équipe qui joue son match à domicile?
4. Retrouver, en parcourant le tableau, les dates des matchs Nice - Marseille (Nice reçoit à domicile) lors des saisons 2002-2003 et 2003-2004.
Compter le nombre de victoires de Nice sur ces 2 matchs.
5. Compter le nombre de matchs Nice-Marseille:
Utiliser la colonne de descripteur equipe_domicile. Utiliser une cellule à la suite du tableau, après la ligne 7221. Dans cette cellule, écrire = NB.SI.ENS(
Avec l’outil d’aide : compléter les champs pour faire la somme de tous les matchs tels que:
equipe_domicile = “Nice”
equipe_exterieur = “Marseille”
Ce qui signifie que vous devrez remplir:
Plage_critères1: F2:F7221
Critères1: “Nice”
…
6. Calculer le score moyen entre ces 2 équipes.
Pour faire ceci:
Utiliser la colonne de descripteur score_domicile. Utiliser une cellule à la suite du tableau, après la ligne 7221. Dans cette cellule, écrire = SOMME.SI.ENS(
Avec l’outil d’aide : compléter les champs pour faire la somme de tous les buts marqués par Nice lorsque l’équipe reçoit Marseille. C’est à dire, lorsque:
critère 1: equipe_domicile = “Nice”
critère 2: equipe_exterieur = “Marseille”
somme_plage: celle de score_domicile
Faire de même pour les buts marqués par Marseille, en utilisant la colonne sous score_exterieur
Enfin: sous le score moyen de Nice: écrire une formule qui calcule le nombre moyen de buts marqués par Nice
Faire de même avec Marseille puis compléter le tableau des scores sur votre feuille de reponse.
data.gouv maires de France
data.gouv
Le site data.gouv.fr est la plateforme des données publiques françaises.
Nous allons consulter les données du Répertoire National des Élus (RNE). Celui-ci a pour finalité le suivi des titulaires d’un mandat électoral. Il est renseigné et tenu à jour par les préfectures et les services du ministère de l’intérieur.
En bas de page, trouver la rubrique elus-maires-mai.csv. Cliquer sur le bouton pour telecharger le document.
Lancer le logiciel Excel. Ouvrir un nouveau classeur, vide.
L’ouverture du fichier va se faire à partir du bandeau Données: Chercher ensuite le bouton importer un fichier texte ou csv. Puis selectionner le fichier.
Exemple d'import d'un fichier .csv depuis le bandeau Données
A l’ouverture du fichier, dans la boite de dialogue, il faudra paramétrer:
l’encodage des caractères (page 1)
dans la page 1, rechercher le menu sur l'encodage des caractères
menu deroulant proposant l'encodage des caractères
la tabulation avec pour separateur le point virgule ; (page 2)
Le paramètre semicolon (point virgule) précise le caractère séparateur.
le format a été correctement renseigné
Traitement du fichier
Le fichier contient des informations basiques sur tous les maires des communes de France. Cela fait un très grand nombre de lignes…
Commençons par reduire l’affichage aux seuls maires du departement 06:
Si la feuille de calcul ne présente pas de filtres en tête de colonnes:
Commencer par selectionner toutes les colonnes A, B, C, D, E dans laquelles se trouvent les données du tableau.
Dans le bandeau Données, choisir Filtrer (entonoir).
Il apparait alors des listes de choix au dessus des descripteurs du tableau. Pour filtrer selon l’un des descripteurs, cliquer sur l’une de ces listes de choix. Celle du Code du departement… et choisir 6
Calculons alors le nombre de maire de sexe feminin.
Dans le classeur, sous le tableau, utiliser l’une des cellules pour placer le calcul du nombre de maires dont le Code sexe est “F”.
Vous allez utiliser pour cela la fonction NB.SI (voir Notice sur support.microsoft.com)
Dans une cellule juste dessous, faire de même pour le nombre de maires de sexe “M”.
Sélectionner ensuite ces 2 cellules et insérer un diagramme circulaire: (dans le bandeau INSERTION)
diagramme circulaire dans le bandeau INSERTION
La proportion joue clairement en faveur des maires de sexe masculin…
un joli camembert
Suite
Rechercher un autre departement pour lequel la parité est mieux respectée…
tableur sur calcu TI83
Utilisation de la base de données
Ouvrir la base de données
Aller sur la page
Exoplanet.eu
Pour consulter la base de données de toutes les planetes observées, cliquer sur Tous les catalogues.
accès à la base de données
Le tableau donne les caractéristiques connues pour ces planètes. Leur nombre est gigantesque. Vous allez utiliser les formules de filtre pour en selectionner quelques unes.
Filtrer
Par exemple, si l’on cherche à étudier les seules planètes telluriques, on choisira celles dont le rayon est un peu supérieur ou un peu inférieur à celui de la Terre.
masse:mjup = masse de la Terre rapporté à celle de Jupiter
On pourrait donc selectionner uniquement les planètes dont la masse (rapporté à celle de Jupiter) est comprise entre 0.001 et 0.004, soit:
$$mass{:}mjup > 0.001 ~AND ~mass{:}mjup < 0.004$$
A vous de jouer:
Dans la barre de formule, vous écrirez la relation qui permettra de filtrer les planètes, et conserver celles dont les masses sont comprises entre 0.001 et 0.004 fois celle de Jupiter.
Ajouter aussi un filtre sur le rayon:
$$radius{:}rjup < 0.1$$
appliquer un filtre sur la base de données
Loi de régréssion linéaire
Entrer les données dans un tableau
On cherche maintenant une loi entre les grandeurs mass et radius pour ces planètes. Le modèle mathematique possible est le suivant:
$$\rho= \tfrac{mass{:}rjup}{(radius{:}rjup)^3}$$
Soit: la masse volumique relative à celle de Jupiter est égale à sa masse relative, divisée par son rayon relatif, à la puissance 3.
Entrer les données dans un tableur:
Sur votre calculatrice Ti-83, commencer par effacer les listes: appuyer sur 2nde + pour accéder au menu mém.
Choisir 4:EffTtesListes
Appuyer sur le bouton stats puis 1:Modifier.
Entrer alors les données issues de la base de données: celle correspondant à mass dans L1 et celles correspondant à radius dans L2
Ajouter en dernière entrée la valeur 0 dans chacune des 2 colonnes (une planète de rayon 0 aura aussi une masse de 0…)
Quitter alors le tableur: 2nde mode ce qui correspond à quitter.
Dans la fenêtre de calcul, saisir: L2^3 puis touche STO → et L3 pour obtenir:
$$L2^3 \rightarrow L3$$
Si vous revenez sur la fenêtre d’edition du tableau, celui-ci devrait ressembler à ceci:
fenêtre tableur de la Ti-83
Afficher le nuage de points
Sur votre calculatrice Ti-83, choisir les listes de valeurs: faire 2nde f(x), ce qui correspond à graph stat. Choisir 1:Graph1...Aff puis:
* Aff
* Type: le nuage de points
* XListe : L3
* YListe : L1
Appuyer alors sur le bouton graphe pour visualiser la distribution de points.
Régréssion linéaire
Appuyer sur le bouton stats, puis menu CALC
Choisir 4:RégLin(ax+b)
Xliste: L3
Yliste: L1
puis descendre et appuyer sur calculer en bas de la fenêtre
Recopier alors le coefficient obtenu pour a. Celui-ci représente la masse volumique relative d’une planète tellurique moyenne, rapportée à celle de Jupiter (1,3g.cm-3).
Prolongement
On pourra faire ce même travail pour une série de planètes gazeuses. Il faudra cette fois choisir des planètes dont les masses et les rayons sont proches de ceux de Jupiter. Par exemple (vous pouvez tester d’autres combinaisons):
mass:mjup> 0.7 and mass:mjup <1.5 AND radius:rjup>0.7
Choisir alors les 10 premières lignes du tableau (il devrait y en avoir plus d’une centaine…). Et faire le même travail que pour les planetes telluriques:
effacer les listes
remplir les listes L1 et L2 avec les valeurs de mass et de radius.
Calculer les valeurs de la liste $L_3 = L_2^3$
tracer la courbe L1 en fonction de L3
Obtenir les coefficients de la regression linéaire pour cette distribution de points.
liens
Les planètes telluriques et gazeuses diffèrent grandement par leur densité, comme on peut le voir sur le dossier suivant: futura-sciences
Exoplanète : première mesure de la densité d’une très jeune planète avec SPIRou: article du CNRS.fr
programmer une fonction python avec des blocs scratch puis recopier le programme python généré
Sous-sections de programmer
de scratch à python
TP1: de scratch à python
Aller sur l’interface de programmation python du site
Vittascience
Partie 1: Premier programme
BUT:
créer un programme qui demande à l’utilisateur son nom, et lui affiche un message de bienvenue.
VARIABLES:
le programme utilise les variables:
nom, de type texte. Contient le nom renseigné par l’utilisateur
debut, de type texte. Contient le mot: “Bonjour "
message, de type texte, contient debut + nom
On rappelle qu’une variable, c’est un nom qui fait référence à une valeur stockée dans un espace de la mémoire. Exemple:
Le nom de variable
ECRIRE LE PROGRAMME:
Dans la fenêtre SCRATCH, on a un seul bloc de code:
Dans la rubrique AFFICHAGE:
selectionner et glisser l’instruction: demander un texte à l’utilisateur.
Comme cette instruction n’est pas complète, elle ne peut pas constituer un bloc de code. Il faut ajouter une affectation.
Dans la rubrique VARIABLE: cliquer sur Créer une variable. Nommer celle-ci nom
Rubrique VARIABLES: selectionner et glisser: Affecter à nom la valeur " ". Puis mettre l’instruction demander un texte à l’utilisateur, et coller les 2 blocs de code.
Rubrique VARIABLES: Créer une nouvelle variable debut. Selectionner et glisser: Affecter à debut la valeur " ". Ecrire "Bonjour "à la place de " ".
Rubrique VARIABLES: créer une nouvelle variable message.
Rubrique MATH: choisir le premier élément, celui qui permet une addition
A l’aide des variables debut et nom, vous allez construire l’instruction complète: Affecter à message la valeur debut + nom
Vous trouverez les éléments debut et nom dans la rubrique VARIABLES:
Compléter alors l’instruction pour obtenir:
Mettre à la suite les blocs de code pour former le programme:
Mettez vous maintenant dans la peau de l’utilisateur: Executer le programme (bouton du haut >) Et repondre à la question dans le shell, sous la fenêtre d’edition.
Sur votre cahier, recopier le script python correspondant. Et répondre aux questions:
Quelle instruction en python permet de demander à l’utilisateur d’entrer une valeur ou un texte?
Quelle instruction python permet d’afficher :
un texte?
le contenu d’une variable?
Quelle instruction en python permet d’affecter le texte “bonjour” à la variable “debut”?
Partie 2: programmer une fonction
But: remplacer les entrées demander à et sortie afficher par des paramètres de fonction
Ecrire le programme
Supprimer le premier bloc du programme précédent (Affecter à nom la valeur demander…)
Rubrique FONCTIONS: Choisir le 2e bloc, Définir nom_de_la_fonction avec l’option retour.
modifier le nom_de_la_fonction: mettre salutation comme nouveau nom
Bouton (+): ajouter le paramètre nom
Votre fonction est vide et ne contient pas encore d’instruction.
Mettre le bloc du programme précédent dans la fonction:
Supprimer la dernière ligne afficher message.
Dans l’espace vide après retour : mettre la variable message pour que celle-ci s’affiche lorsque l’on appelle la fonction:
Executer le programme (bouton du haut >) En apparence, il ne se passe rien, mais vous avez quand même chargé la fonction en mémoire.
Dans le shell (partie inférieure de la fenêtre), après les chevrons >>>, saisir l’instruction qui va appeler votre fonction:
>>>salutation("votre nom")
Modifier votre nom par votre veritable nom…
Sur votre cahier, recopier le script python correspondant. Et répondre aux questions: Dans le script python: …
Quelle partie du programme associe votre nom à la variable nom?
Quelle partie du programme affiche le contenu du message?
Comment sont mises les instructions du bloc de code dans la fonction?
Comment faut-il faire pour appeler la fonction et déclencher son execution?
Quel est l’avantage d’utiliser une fonction plutôt que le script de la partie 1?
Utiliser la calculatrice TI-83 Premium CE edition Python
S’il vous reste du temps, recopiez ce programme dans l’environnement python de la calculatrice. Executez le.
Ti83 prise en main
mettre a jour et tester les scripts python sur la calculatrice
Ti83 et mise a niveau microbit
mettre a jour charger les modules pour la connexion de la carte microbit avec la calculatrice TI83
Ti83 microbit prise en main
tester la connexion de la carte microbit avec la calculatrice TI83
Loi de Mariotte
TP utilisant la calculatrice TI83, l’extension avec la carte microbit et le dispositif de mesure de pression volume
informatique des objets
presentation de la carte microbit
capteurs integres
capteurs de la carte microbit
niveau a bulles
microbit capteur de direction, inclinaison, jeu du snake
MB grove
shield groove, capteurs passifs
MB LED clignotante
shield groove, circuit electronique a LED
MB diviseur de tension
microbit CTN et pont diviseur de tension, capteur photosensible
Capteur lumiere
capteur integre, mesure et detection de clarté obscurité, chaine de caracteres
MB sons
jouer des sons avec le HP de la carte microbit
mesure de c du son
microcontroleur microbit avec extension ultrasons pour effectuer les mesures et traitement python
portes logiques
etude des portes logiques en circuit integré, branchements sur la carte microbit
loi de Mariotte
mesure dispositif, copie des valeurs depuis REPL et traitement python
reseau radio SNT
decouverte et programmation de la carte microbit, fonction radio
reseau radio 1ere
programmation de la carte microbit, fonction radio, niveau 1ere NSI
reseau radio term
sequence reseau de niveau terminale NSI
Chiffrement
TP chiffrement a partir d’un reseau de cartes microbits communiquant par radio, niveau term NSI
TP utilisant la calculatrice TI83, l’extension avec la carte microbit et le dispositif de mesure de pression volume
Sous-sections de Texas instruments
Ti83 prise en main
Mettre à jour la calculatrice TI-83 Premium CE
Installer TI CONNECT sur votre ordinateur
page Produits du site
Cliquez sur l’onglet Mises à jour et logiciels et choisir Logiciel Ti-connect
Télécharger le logiciel Ti-Connect le plus récent
Choisir la bonne version du logiciel et installez le logiciel TI CONNECT sur votre ordinateur: Executer le fichier téléchargé et suivre les instructions d’installation.
Cliquer sur le bouton télécharger. Choisir alors le modèle de la calculatrice: Ti-83 Premium CE Edition Python.
Choisissez le modèle de votre calculatrice
Au bas de la page, choisissez Télécharger le bundle (OS + applications):
Télécharger le système d'exploitation le plus récent pour votre calculatrice
Lancer le logiciel TI CONNECT et brancher la calculatrice sur le port USB de votre ordinateur (cable USB vers usb B fourni).
connexion calculatrice - ordinateur
Cliquer sur
l’explorateur de calculatrice(1),
puis sur ajouter les données de l’ordinateur vers la calculatrice connectée(2).
explorateur de calculatrice sur TI CONNECT
L’explorateur de votre ordinateur devrait vous permettre de retrouver le fichier TI83CEBundle-5.8.0.22.b83 (la version peut différer au moment de votre téléchargement).
Sélectionner le fichier.
Suivre les instructions d’installation.
Testez votre premier script Python
Video Yvan Monka: prise en main de la Ti83 Ed python
Utiliser des extensions
Modules python
On pourra ajouter des modules pour:
utiliser turtle python
représenter des vecteurs
réaliser des diagrammes en barre ou en boîte à moustache.
Le fichier devrait alors se trouver dans votre dossier téléchargements.
Téléverser les modules dans la calculatrice
Lancer le logiciel TI CONNECT et brancher la calculatrice sur le port USB de votre ordinateur (cable USB vers usb B fourni).
connexion calculatrice - ordinateur
Suivre la même procédure que pour la mise à jour de la calculatrice: Cliquer sur ajouter les données de l’ordinateur à la calculatrice connectée. Et ajouter le module à installer.
Chaine Youtube pour pour utiliser la calculatrice TI-83 Premium CE Python avec le microcontrôleur micro:bit : lien
Ti83 et mise a niveau microbit
Mettre à jour la calculatrice TI-83 Premium CE
Installer TI CONNECT sur votre ordinateur
Choisissez le modèle de votre calculatrice
Cliquez sur le bouton Suivant.
Télécharger le logiciel Ti-Connect le plus récent
Installez alors le logiciel TI CONNECT sur votre ordinateur: Executer le fichier téléchargé et suivre les instructions d’installation.
Mettre à jour la calculatrice
Sur la même page du site Texas-Instruments:
Télécharger le système d'exploitation le plus récent pour votre calculatrice
Lancer le logiciel TI CONNECT et brancher la calculatrice sur le port USB de votre ordinateur (cable USB vers usb B fourni).
connexion calculatrice - ordinateur
Cliquer sur
l’explorateur de calculatrice(1),
puis sur ajouter les données de l’ordinateur vers la calculatrice connectée(2).
explorateur de calculatrice sur TI CONNECT
L’explorateur de votre ordinateur devrait vous permettre de retrouver le fichier TI83CEBundle-5.5.2.44.b83 (la version peut différer au moment de votre téléchargement).
Sélectionner le fichier.
Suivre les instructions d’installation.
Testez votre premier script Python
Video Yvan Monka: prise en main de la Ti83 Ed python
Utiliser des extensions
Préparer la calculatrice pour utiliser la carte micro:bit
Ti-83 Premium CE Python et micro:bit
Télécharger les modules
Se rendre du la page de téléchargement du site Texas Instrument:
Lien
Vous pouvez télécharger l’ensemble de ces fichiers, en un seul clic, depuis
la page du site Texas instruments
Téléchargez le dossier “modules_microbit V1.zip” ou “modules_microbit V2.zip” selon le modèle de carte dont vous disposez
Ceux-ci devraient se trouver dans votre dossier téléchargements.
Téléverser les modules dans la calculatrice
Lancer le logiciel TI CONNECT et brancher la calculatrice sur le port USB de votre ordinateur (cable USB vers usb B fourni).
connexion calculatrice - ordinateur
Suivre la même procédure que pour la mise à jour de la calculatrice: Cliquer sur ajouter les données de l’ordinateur à la calculatrice connectée. Et sélectionner en une seule fois tous les modules à installer:
MICROBIT.8xv
MB_GROVE.8xv
MB_SENSR.8xv
MB_RADIO.8xv
MB_PINS.8xv
MB_BUTNS.8xv
MB_DISP.8xv
…
Liens
Prise en main de la calculatrice et autres tips: letutosmaths
Prise en main du module Python sur la calculatrice TI-83 avec Ti codes
Chaine Youtube pour pour utiliser la calculatrice TI-83 Premium CE Python avec le microcontrôleur micro:bit : lien
Ti83 microbit prise en main
La carte micro:bit peut être programmée à partir de la calculatrice TI-83 edition python. La programmation se fait en langage Python.
Préparer le matériel
Commencer par mettre à jour la calculatrice TI-83 Premium CE edition Python. Voir la fiche explicative. Téléchargez également tous les modules necessaires pour piloter la carte microbit, avec la calculatrice. Voir fiche.
Puis changer de cable pour brancher la carte micro:bit sur l’ordinateur (cable USB: ordinateur vers micro usb B : microbit).
la fenêtre du shell Python s’ouvre alors. Vous pouvez selectionner l’une des options du menu en bas de l’écran à l’aide des touches f(x), fenêtre, … Ici, vous allez choisir Nouveau.
Saisir le nom de votre premier programme puis valider (par exemple MBINIT puisque vous demarrez un premier script d’initiation à la carte microbit).
Pour importer la librairie microbit dans votre programme, aller dans le catalogue pour selectionner l’instruction from SCRIPT import *: Faire 2nde 0 qui lance le menu catalogue, puis la touche alpha et F. Selectionner la ligne from SCRIPT import *
ecrire le nom du module microbit à la place du mot SCRIPT
A partir de maintenant, les autres modules relatifs à la carte micro:bit seront ensuite appelés à partir du menu « microbit »
qui vient d’être rajouté dans les modules.
Saisir le script
A la ligne suivante de votre script, vous allez ajouter la librairie qui pilote l’affichage de la carte micro:bit:
menu du bas de la fenêtre Fns: Selectionner le menu Module en vous deplaçant avec les flèches.
Choisir 8:micro:bit puis 1:affichage, ce qui devrait ajouter la ligne from mb_disp import *
Dans le menu des Modules, il est apparu une nouvelle collection d’instructions: 9:affichage. Choisir cette collection puis choisir 1.clear()
Faire de même et choisir cette fois 2.show de cette même collection. Cela devrait afficher display.show(,delay=400,wait=True).
Le curseur clignote au niveau du premier paramètre que vous devrez renseigner: mettez "Image.HAPPY" à l’aide de l’editeur de texte (bouton du bas a A #). Valider les symboles avec la touche entrer. Faites Coller lorsque vous avez terminé la saisie.
Votre programme devrait ressembler à ceci:
Executer
Relier alors la carte micro:bit à la calculatrice à l’aide du cable usb mini B vers micro B.
Puis executer le script: Option Exec de la fenêtre d’edition…
A vous de jouer: remplacer l’image HAPPY par celle Image.SAD
Capteur grove MPX5700AP capable de mesurer la pression de l’air dans une plage de 15 kPa à 700 kPa. Sensibilté 6,4 mV/kPa.
Notice
Les différents programmes PRESS.8xv et BOYLEMAR.8xv seront déjà installés sur la calculatrice. Celle-ci devra être préparée avec les librairies utiles selon la procédure expliquée sur la Fiche de prise en main
Préparer le matériel
La carte microbit doit être équipée du shield grove.
Connecter la calculatrice sur la carte microbit.
Connecter le capteur de pression sur le shield (entrée PIN0).
Mettre la seringue dans la position 12mL et fermer celle-ci sur le capteur.
Lancer le programme
Sur la calculatrice: Touche prgm: Choisir 2-Python App
Dans la liste des programmes installés: Choisir BOYLEMAR avec le curseur. Valider avec la touche entrer.
Touche var. Choisir la fonction mesure(). Valider avec OK (touche graphe).
Vous avez alors 3s pour positionner et maintenir la seringue sur le volume 2mL comme indiqué sur l’écran. Puis à nouveau 3s pour chacun des autres volumes proposés…
Une fois la serie de mesures réalisée, le graphique P-V est affiché à l’écran.
Pour prendre connaissance et traiter les données:
Revenir en mode calculatrice: touche on puis 2ndemode(quitter). Valider.
touche stats puis 1:modifier. La liste 1 est celle du volume(mL) et la liste 2 celle de la pression(kPa).
TP chiffrement a partir d’un reseau de cartes microbits communiquant par radio, niveau term NSI
Sous-sections de Microbit
informatique des objets
Prise en main de la carte micro:bit: présentation
La carte microbit est un nano-ordinateur créé pour la promotion de la programmation dans l’éducation. Elle est très simple d’utilisation, mais peut également s’intégrer dans des applications complexes.
Gipsy est prête.
Elle possède dans sa version 2:
un capteur de luminosité
un acceleromètre/gyroscope
un capteur de champ magnétique
2 boutons a/b
un écran LED 5*5
un mini haut-parleur
un microphone
antenne radio 2,4 GHz et bluetooth pour une communication entre cartes
3 entrées/sorties analogiques ou numeriques(0-3,3V), avec un courant de sortie limité à 200mA. Par défaut les broches sont configurées en sortie.
La programmation se fait depuis un navigateur web en Block Editor pour les débutants ou en langage MicroPython pour les utilisateurs plus expérimentés.
Le programme se télécharge depuis l’IDE en ligne et se copie simplement dans la micro:bit comme dans une clé USB (cordon USB vers micro-USB non inclus).
Lui donner un nom (champ en haut à droite : script name).
Charger le programme sur le disque dur de l’ordinateur : Download (l’extension est .hex)
Deplacer le programme sur la carte microbit à l’aide de l’explorateur de fichiers.
Utiliser l’editeur Mu
Bouton Mode : choisir l’editeur BBC microbit
Saisir le script dans la fenêtre de script.
Faites une copie de votre script :
Une fois le microcontrôleur relié à l’ordinateur par le cable USB : bouton Flasher pour transferer le script.
L’editeur aide à la saisie grâce à l’autocompletion. Selectionner le mot en python et valider avec la touche Enter du clavier.
Lorsque l’on tape le nom d’une fonction qui est documentée, l’aide apparait à l’écran. C’est très utile pour savoir si la fonction prend des paramètres :
gestion des erreurs de syntaxe
Une fois le programme chargé, il peut y avoir une erreur de syntaxe qui empêche son fonctionnement. Le message s’affiche sur l’écran de la carte microbit. Mais il peut être plus facile de lire ce message sur l’écran de l’ordinateur. Le bouton REPL fournit une console python avec affichage des messages à l’execution.
Un premier programme Hello World
Entrées/Sorties :
La carte dispose d’un petit écran de LED qui peut servir de sortie et d’affichage. Elle est équipée de 2 boutons A et B pour intéragir.
Pour que le programme détecte l’appui sur les boutons, il faut surveiller l’état des boutons en permanence, avec une boucle non bornée while True:
On demarrera toujours le script avec l’import des librairies spécifiques à la carte micro:bit : from microbit import *, qui s’ajouteront aux librairies standart Python :
frommicrobitimport*# On cree une boucle infinie whileTrue:ifbutton_a.is_pressed():display.show(Image.HAPPY)else:display.show(Image.SAD)
Ici, le programme affiche l’un ou l’autre des smileys, selon si le bouton A est pressé ou relâché.
Si l’on veut afficher un texte, il sera préférable d’utiliser la fonction scroll à la place de show, afin de faire défiler les caractères sur l’écran de LED.
Exemple avec un texte :display.scroll("Hello World")
Exemple avec la valeur d’une variable dt :display.scroll(dt)
Affichage de formes
Ce script met en oeuvre une boucle bornée qui permet de parcourir les pixels (selon x ou y):
# trace un trait horizontal (-)frommicrobitimport*y=2b=9forxinrange(5):display.set_pixel(x,y,b)
x,y : int, valeur de 0 à 4
b : int, 0 à 9 (intensité lumineuse de la diode en x,y)
La carte microbit dispose de plusieurs capteurs intégrés:
temperature
acceleromètre à 3 axes
mesure de champs magnétique
luminosité
Mesure d’horizontalité
Principe
On utilisera le capteur “acceleromètre”.
Le champs de pesanteur génère une force, le poids, qui peut être mesurée par l’acceleromètre. Une des applications principale des accéléromètres est le calcul d’inclinaison. Ca permet de savoir comment est orienté votre microcontrôleur par rapport à la terre. C’est ainsi que sur un smartphone, celui-ci passe du mode portrait au mode paysage par rotation d’un quart de tour.
C’est un composant électronique qui réalise cette mesure: une tige de silicium est chargée électriquement et la cage dans laquelle elle se trouve également, le déplacement de charges portée sur la tige est détectable et on en déduit le sens du déplacement.
source
principe d’un accéléromètre électromécanique (la partie rouge se met en mouvement par rapport au reste et le décalage est détecté grace au déplacement de charge qu’elle porte) —
Script 1
Ce programme lit les valeurs toutes les 100 ms et affiche une flèche correspondant à la direction du mouvement sur l’écran micro:bit.
La mesure de l’acceleration est faite dans la direction X:
L’écran montre un pixel qui sera bien centré si le micro:bit est bien à l’horizontale ou qui sera décalé en direction de l’inclinaison dans le cas contraire. Le but est donc de mettre le micro:bit parfaitement à plat, de sorte qu’uniquement la LED centrale soit allumée.
source
Le programme permet de stocker dans les variables incli_X et incli_Y les valeurs mesurées par l’accéleromètre.
Vous pouvez charger ce programme dans la carte microbit. Puis ouvrir la console de l’editeur MU (REPL), et afficher les valeurs de ces variables: (ces valeurs dependent de l’inclinaison initiale de la carte microbit)
>>> incli_X
228
>>> incli_Y
-15
Refermez alors la console et revenir sur l’editeur de script…
Compléter le script avec les tests qui permettront d’afficher “D”, “G”, “H”, “B” ou “-” selon si l’inclinaison est vers la Droite, Gauche, Haut, Bas, ou - neutre.
On pourra se conformer au diagramme ci-dessous:
diagramme de décision if ... elif ... else
Flasher. La lettre qui est affichée depend alors de l’inclinaison!
sauvegarder le fichier .pydans votre classeur numérique (vos documents, dans un dossier particulier)
Afficher une bulle
L’inclinaison va maintenant mettre en mouvement une bulle à l’écran. (Un pixel de coordonnées x, y).
On définit les variables x, y = 2, 2 avant la boucle principale while True.
Boucle principale
On remplacera ensuite chacune des instructions d’affichage display.show() par la mise à jour d’une variable direction:
display.show("D")# sera remplace pardirection="D"
à la fin de la boucle, on ajoutera les lignes qui vont:
appeler la fonction deplace avec les arguments: direction, x, y. Affecter à x, y les valeurs de retour.
Le corps du programme devrait alors ressembler au script suivant:
frommicrobitimport*defdeplace(direction,pos_X,pos_Y):# a completerreturnpos_X,pos_Yx,y=2,2whileTrue:incli_X=accelerometer.get_x()incli_Y=accelerometer.get_y()ifabs(incli_X)>abs(incli_Y):ifincli_X>20:direction="D"elifincli_X<-20:#display.show("G")direction="G"else:direction="-"else:ifincli_Y<-20:direction="B"elifincli_Y>20:direction="H"else:direction="-"x,y=deplace(direction,x,y)sleep(100)display.clear()display.set_pixel(x,y,9)
Programmer une fonction avec paramètres
La fonction sert à modifier les valeurs des paramètres pos_X et pos_Y selon celle de direction.
direction est une variable de type str et vaut “D”, “G”, “H”, “B” ou “-”.
pos_X et pos_Y sont de type int.
Les valeurs de retour sont pos_X et pos_Y.
defdeplace(direction,pos_X,pos_Y):# a completerreturnpos_X,pos_Y
Il faudra donc programmer une série de conditions sur direction pour modifier les valeurs de position (augmenter ou diminuer d’une unité pos_X ou pos_Y).
Problème de depassement: Les valeurs admises pour pos_X et pos_Y doivent être comprises en 0 et 4, sinon cela génère un Value Error lorsque l’on veut afficher le pixel à l’ecran avec display.set_pixel(x,y,9).
Votre fonction doit aussi prendre en compte cette possibilité et ne pas retourner de valeur <0 ou >4.
pencher la carte microbit vers la droite
Flasher et testez votre programme. Parviendrez-vous à maintenir le pixel au centre pendant quelques secondes?
sauvegarder le fichier .py
Prolongement: Le SNAKE
On peut augmenter la complexité du programme en affichant un serpent à l’écran comme dans le jeu snake. Les coordonnées des pixels du serpent sont alors stockées dans une Liste [(x1,y1),(x2,y2),...] pour permettre leur affichage:
A chaque déplacement, cela ajoute un pixel à la fin de la liste. Il s’agit de la tête du serpent. Il faut alors retirer le premier pixel (serpent[0]) si l’on veut que sa longueur reste constante.
deplacement du serpent vers le bas
Dans la boucle principale, une fois que la variable directiona été mise à jour, on ajoutera les lignes suivantes pour la gestion du deplacement du serpent:
L’objet serpent est alors une liste Python à laquelle on associes les fonctions tete, ‘ajoute_tete, supprime_queueet affiche`.
Ces fonctions sont décrites dans les commentaires suivants:
deftete(S):# retourne les coordonnees x, y de la tete du serpent# qui sont stockees dans le dernier element S[-1]# sous la forme d'un tupple (x,y)defajoute_tete(S,x,y):# ajoute un tupple (x,y) a la fin de la liste S defsupprime_queue(S):# decale toutes les valeurs de la liste S vers la gauche:# a l'aide d'une boucle bornee sur les indices i:# copie toutes les valeurs S[i+1] dans S[i]# puis supprime le dernier elementdefaffiche(S):# affiche tous les pixels du serpent# a partir de leurs coordonnees dans S
Il restera à écrire le script de ces fonctions. Cette méthode de programmation introduit le chapitre sur les types construits en Terminale NSI: On s’intéresse d’abord à l’interface de ce nouveau type appelé serpent. Puis à son implémentation.
interface: Ce que réalisent les fonctions associées au type construit. Comment on les utilise.
La carte microbit associée au shield grove permet d’utiliser de nombreux capteurs passifs. L’instruction à utiliser: pin0.read_analog(). Cette instruction permet la lecture d’une tension de type analogique sur l’entrée PIN0, quel que soit le composant passif.
Matériel
carte microbit et shield grove
capteur de luminosité grove ou autre capteur passif
eventuellement: lampe de bureau, filtres occultants
On utilise le connecteur grove du microbit pour commander une sortie en tension. On pourra allumer, et faire clignoter une LED, branchée en série avec sa resistance de protection.
Il faudra utiliser les connecteurs avec fils de couleur sur prise grove:
Jaune: tension commandée : relier au + de la LED
Noir: GND : relier à la resistance 1k
Rouge (3V fixe) et Blanc: non utilisés
circuit avec LED et Resistance
montage complet
Matériel
carte micro:bit et shield grove
fil de connexion grove-connecteurs couleur (rouge noir blanc jaune)
pince crocodile
Diode electroluminescente LED
resistance de 1kΩ
multimètre
Script
# Jaune: tension commandée : relier au + de la LED # Noir: GND : relier à la resistance 1k# Rouge et Blanc: non utilisésfrommicrobitimport*whileTrue:pin0.write_digital(1)# sortie 3Vsleep(1000)pin0.write_digital(0)sleep(1000)
MB diviseur de tension
luminosité LDR et diviseur de tension
Principe
La LDR est un composant électronique photosensible. Sa valeur de résistance diminue avec la luminosité.
Pour constater ces variations, on utilisera la LDR dans un montage type diviseur de tension.
Un seul des connecteurs grove de la carte micro:bit suffira pour alimenter le circuit et mesurer la tension au milieu du pont diviseur. Il faudra utiliser les connecteurs avec fils de couleur sur prise grove:
Rouge: Alimentation fixe 3V avec l’instruction pin0.write_digital(1)
Noir: GND
Jaune: pour la mesure de tension avec l’instruction pin0.read_analog()
circuit avec LDR et Resistance
montage à réaliser
Matériel
carte micro:bit et shield grove
fil de connexion grove-connecteurs couleur (rouge noir blanc jaune)
pince crocodile
Photoresistance type VT900 serie (light dependant resistor LDR)
Le projet consiste à créer un motif lumineux sur la grille de DEL de la carte micro:bit. La nature du motif et l’intensité des DEL dépendra de la lumière ambiante: l’affichage sera plus lumineux si l’environnement est sombre.
clair- obscur
Prise en main du capteur
Pour ce projet, le panneau de DEL peut être utilisé en capteur de luminosité basique en inversant la polarisation des DEL.
Celles-ci sont alors utilisées comme capteur de lumière.
Le capteur de lumière de la micro:bit mesure la lumière dans une gamme allant de 0 (très sombre) à 255 (très lumineuse).
La mesure du niveau de luminosité passe par la commande ci-dessous.
frommicrobitimport*display.read_light_level()
On peut stocker cette valeur dans une variable, par exemple:
Adapter le script 1 pour afficher un carré très lumineux lorsqu’il fait sombre, ou faiblement lumineux lorsqu’il fait clair. Appeler ce nouveau script: script 2
Question b: Concevoir et tester le script 2. Recopier le script sur votre feuille.
Version 3: Affichage d’intensité variable
L’intensité lumineuse du motif affiché dépend de la valeur attribuée à chaque pixel:
‘99999:90009:90009:90009:99999:’: motif d’intensité forte
On peut créer une chaine de caractères en fonction d’une variable I qui varie de 0 à 9 et qui dessine un motif carré. Les 2 premieres lignes du motif sont construites à partir de:
motif = str(I + I + I + I + I + ":" + I + "000" + I + ":")
La valeur de I sera calculée d’après la variable lumiselon la loi:
I=int((255-lumi)/255*9)
Le programme principal du script 3 (à compléter) sera alors:
Afficher avec le script 3 un carré dont l’intensité lumineuse varie entre 0 et 9 selon l’intensité lumineuse mesurée. Tester et mettre au point le programme.
Question c: Recopier sur votre feuille le script 3.
Prolongement 1: utiliser des fonctions
Le script 3 peut être amélioré en utilisant des fonctions.
Le programme principal:
Ajouter les definitions des fonctions intensite et carre au script 3. Appeler ce nouveau script: le script 4.
Aides:
La fonction intensite retourne une valeur de 0 à 9 selon la variable lumi en argument:
defintensite(lumi):"""retourne une valeur de 0 a 9
9 <=> lumi = 0
0 <=> lumi = 255
Exemples:
>>> I = intensite(255)
>>> print(I)
0
>>> I = intensite(0)
>>> print(I)
9
"""returnint((255-lumi)/255*9)
La fonction carre qui prendra en paramètre la valeur I, retourne une chaine de caractères dans le bon format pour dessiner les contours d’un carré vide en son centre.
Question d: Programmez et testez le script 4. Recopiez le sur votre feuille.
Prolongement 2: motif animé
On pourra remplacer l’image fixe par une animation. Il faudra alterner avec 3 images successives, et attendre un delai de 100ms entre chaque. Utiliser pour cela la fonction sleep(100) entre chaque affichage.
Et ajuster l’intensité lumineuse du motif affiché selon l’éclairage mesuré (voir script 4).
TP : Mesure d’une durée de propagation d’ultra-sons
Principe
On cherche à mesurer la durée de propagation des ultra-sons lors de leur reflexion sur un obstacle.
Dispositif
Pour une distance d1 entre le dispositif ultra-sons et l’écran, on relève la durée de propagation t (en micro secondes) sur la carte microbit.
Cette mesure est déclanchée par l’appui sur le bouton a de la carte microbit.
Script
Commencer par uploader le script ci-dessous dans la carte microbit selon la méthode utilisant l’editeur Mu (flasher): voir page présentation microbit
Mu editor
frommicrobitimport*frommachineimporttime_pulse_usimporttime,music,mathanalogiq_in=[pin1]defmesure_temps_A_R(broche=pin1):"""Module Grove - Ultrasonic Ranger
Retourne la durée d'un aller/retour des ultra_sons en microsecondes
Paramètre : Nom de la broche utilisée
"""broche.write_digital(0)time.sleep_ms(2)broche.write_digital(1)time.sleep_ms(10)broche.write_digital(0)broche.read_digital()dt=time_pulse_us(broche,1)returndtwhileTrue:ifbutton_a.is_pressed():dt=mesure_temps_A_R()display.scroll(dt)
Brancher le dispositif à ultra-sons
Brancher l’emetteur-capteur à ultra-son sur la carte micro:bit. Choisir le port groove appelé PIN1 sur la carte.
Diriger l’emetteur-capteur à ultra-sons vers un support rigide, afin que les ondes ultrasonores se reflechissent et reviennent vers le recepteur.
Mesures
Une fois le script téléversé :
Lorsque l’on appuie sur le bouton A, la fonction mesure_temps_A_R permet de communiquer avec l’emetteur-capteur à ultra-son. L’affichage de la durée de propagation pour un aller-retour s’affiche sur l’écran LED du microcontrôleur, chiffre après chiffre (scroll). La durée est en µs.
Exemple d’affichage d’une durée dt = 833µs:
En positionnant l’emetteur-capteur à environ 15 cm d’un support reflechissant, on lit :
En supposant que la célérité du son vaut 340m/s au moment de l’experience, cela donne une distance parcourue de $340 \times 833.10^{-6} = 0,28m$, double de la distance au support.
Cela semble cohérent. Mais il faudrait discuter de la précision attendue sur les 2 derniers digits mesurés par le dispositif…
exploitation des mesures
Répeter les mesures et relever la durée mise par les ultra-sons pour se reflechir sur un support rigide. Sur le cahier, consigner les données dans un tableau:
distance parcourue (m)
0
0.25
0.5
1.0
…
temps (s)
0
..
..
..
..
Ouvrir un editeur Python, comme par exemple Pyzo, et saisir le script ci-dessous. Enregistrer le programme dans vos Documents avec une extension .py, comme par exemple: courbe.py
Modifier les valeurs dans les listes X et Y afin d’afficher la courbe de la distance parcourue en fonction du temps (Y = distance; X = temps).
Relever alors l’équation de la courbe modélisée, déterminer la célérité des ondes c, ainsi que le coefficient de correlation.
QUESTIONS: Dans le programme python ci-dessous, quelle partie du script correspond à:
l’import de librairie
la définition des listes X et Y
le traitement statistique des données
l’affichage du graphique
importmatplotlib.pyplotaspltimportnumpyasnpfromscipy.optimizeimportcurve_fitfrommatplotlib.widgetsimportCursor#--------------------------------------------------#création des listes de variables utilisées dans le programme#--------------------------------------------------X=[0,1,2,3,4,5]Y=[0.0,1.1,1.9,3.0,4.1,4.9]#--------------------------------------------------#partie modélisation#--------------------------------------------------#variables utilisées dans la modélisation polynomiale standarda=0.9b=0#mise en place de l'outil curve fit (scipy)deffunc(x,a,b):returna*x+bX=np.asarray(X)# conversion des listes en matrices Y=np.asarray(Y)# pour pouvoir calculer a*X+by=func(X,a,b)params,mcov=curve_fit(func,X,Y)# params = coefficients retournés par le calcul de modélisation avec R2 minimal# mcov = matrice de covariance, permet de quantifier la variation de chaque variable par rapport à chacune des autresa=params[0];b=params[1]#--------------------------------------------------#partie calcul de r2 coefficient de correlation#--------------------------------------------------residuals=Y-func(X,params[0],params[1])ss_res=np.sum(residuals**2)ss_tot=np.sum((Y-np.mean(Y))**2)r_squared=1-(ss_res/ss_tot)print(r_squared)#-------------------------------------------------# partie graphique avec quadrillage#-------------------------------------------------# label et config des axesplt.xlabel('X (s)')plt.ylabel('Y (m)')# Plotplt.plot(X,Y,'o')# nuage de points de l'acquisitionplt.plot(X,func(X,a,b),'g',linewidth=1)# courbe modeliseeequation="Y = "+str(round(a,3))+" * X + "+str(round(b,3))+", coef correlation r2 = "+str(round(r_squared,5))plt.legend(["mesures","courbe modélisée"])plt.title(equation)# modifier les axes APRES avoir positionné les points si besoin de choisir l'echelleaxes=plt.gca()cursor=Cursor(axes,useblit=True,color='red',linewidth=2)# affichageplt.show()
Vous allez étudier les portes logiques fournies pour la seance. Vous utiliserez une carte microcontrôleur Microbit pour disposer d’une générateur de tension à 2 sorties. Chacune de ces sorties sera branché à l’une des entrées de la porte logique. Les boutons de la carte microbit serviront à choisir le niveau de tension 0 ou 3,3V pour les entrées de la porte logique.
Dans un premier temps, vous allez consulter la fiche du TP sur le clignottement d’une Diode Electroluminescente.
Ce que doit réaliser le programme: On pilote les niveaux de tension PIN0 et PIN1 à l’aide des boutons a et b de la carte microbit:
bouton
niveau de tension
a relâché
PIN0 à 0V
a appuyé
PIN0 à 3,3V
b relâché
PIN1 à 0V
b appuyé
PIN1 à 3,3V
Sur l’editeur Mu: Copier et compléter le programme suivant. Brancher la carte microbit sur un port USB de l’ordinateur (maintenir le câble au cours de la seance). Et flasher la carte (charger le programme).
# Ecrit ton programme ici ;-)# Jaune: tension commandée : relier au + de la LED # Noir: GND : relier à la resistance 1k# Rouge du PIN1 : relier à la borne +Vcc du circuit integre# Blanc: non utilisesfrommicrobitimport*whileTrue:ifbutton_a.is_pressed():# à completer
PIN0 et PIN1 de la carte
Brancher les connecteurs grove sur les PIN0 et PIN1. Utiliser alors des fils electriques pour acceder aux contacts des connecteurs grove:
PIN0: contact noir (0V)
PIN0: contact jaune (0 ou 3,3V selon le programme)
PIN1: contact noir (0V)
PIN1: contact rouge (3,3V fixe)
PIN1: contact jaune (0 ou 3,3V selon le programme)
conneceurs grove de la carte microbit
Relier alors les contacts noirs et jaune de chaque connecteur grove sur une ligne verticale de la plaquette d’essai (breadboard).
connection carte microbit sur breadboard
Premiers essais
On va maintenant utiliser la diode electroluminescente pour tester si le programme fonctionne: Brancher la diode en série avec sa resistance de protection $1k\Ohm$ aux bornes de la tension du PIN0 (entre les contacts jaune et noir).
Branchement en serie de la DEL
Tester si celle-ci s’allume lorsque l’on appuie sur le bouton.
Cabler la porte logique
Les circuits intégrés fournis pour la seance sont de différents types. Certaines possèdent des portes logiques à 2 entrées (AND, OR, NAND), alors que celle NAND ne possède qu’une entrée. Des marques de couleur ont été peintes pour les identifier plus facilement:
code
porte logique
4081 (bleue)
AND
4071 (orange)
OR
4011 (jaune)
NAND
4069 (vert)
NOT
Chaque circuit intégré comporte plusieurs portes logiques. Pour celles à 2 entrées, on peut les repérer comme sur le schéma suivant:
Portes logiques à 2 entrées
Pour le circuit NOT, à une entrée, la disposition des portes logiques est comme ceci:
Portes logiques NOT
Disposer le circuit integré jaune 4011 sur le breadboard
selectionner l’une des portes logique du composant
Brancher la diode avec, en serie, sa resistance de protection à la sortie de la porte logique. Fermer le circuit de la diode sur l’un des contacts noirs (0V) de PIN0 ou PIN1.
alimenter le circuit intégré: brancher la borne +Vcc sur le contact rouge du PIN1 (3,3V) et la borne GND (masse) sur l’un des contacts noirs (0V) de PIN0 ou PIN1.
branchement de la diode en sortie
brancher les contacts commandés (jaunes) des PIN0 et PIN1 sur les entrées de la porte logique
circuit complet
Actionner alors les boutons a et b de la carte microbit pour tester toutes les combinaisons possibles en entrée. Renseigner la table de vérité.
E1
E2
S
0
0
0
1
1
0
1
1
Prolongements
Modifier le montage pour tester les autres portes logiques fournies.
loi de Mariotte
Loi de Mariotte - utilisation d’un dispositf à microcontrôleur
Dispositif
La seringue est branchée sur le capteur de pression, lui-même relié au port grove PIN0 de la carte microbit.
La carte est branchée sur un port USB de l’ordinateur.
L’écran LED de la carte microbit affichera la valeur de la tension sur PIN0.
Grâce à sa liaison série sur le port USB, le logiciel Mu affichera les données mesurées au cours de l’acquisition sous un format: [(volume1, tension1), (volume2, tension2), ...]
Editeur Mu
Lancer l’editeur Mu. Choisir au demarrage le mode BBC microbit.
Dans la fenêtre d’edition, coller le script suivant:
Ecrire dans la cellule du notebook datas = et coller les valeurs mesurées.
A la suite, coller le script suivant:
importmatplotlib.pyplotaspltvolume=[]tension=[]inv_volume=[]pression=[]formesureindatas:volume.append(mesure[0])tension.append(mesure[1])plt.xlabel("Volume mL")plt.ylabel("Tension")# Plotplt.plot(volume,tension,'o')# nuage de points de l'acquisition# affichageplt.show()
Executer la cellule (Maj + Entrée) ou bonton triangle sur la barre de commande du logiciel.
Quelle est l’allure de la courbe tension = f(volume)?
Etude de l’evolution de la pression
Dans la boucle : for mesure in datas:, ajouter les instructions qui permettront de completer la liste inv_volume. On veut mettre dans cette liste inv_volume les valeurs calculées à partir de $1 / volume$
Comme les valeurs du volume sont mises dans mersure[0]cela donne dans le script python:
Prise en main de l’interface microbit sur Vittascience
Ce premier travail permet de découvrir l’interface Vittascience.com pour la programmation de la carte microbit. Les questions qui suivent cette manipulation vont présenter le langage Python. Aucune connaissance du langage n’est requise pour ce premier travail.
Brancher la carte microbit sur l’un des ports USB de l’ordinateur. La carte est alors visible depuis l’explorateur comme une nouvelle mémoire flash.
Premier programme
La page présente 2 espaces. L’edition du programme se fait dans la partie gauche (celle présentant les blocs à assembler). A droite, c’est la traduction du programme en langage Python, qui est réalisée de manière automatique.
Le programme en langage Python est alors:
frommicrobitimport*whileTrue:pass
En colorant les différentes parties du script Python, on peut mettre en correspondance: les blocs et leur équivalent en langage informatique:
Mettre un bloc de type affichage sur la carte microbit, comme illustré ci-dessous:
Modifier l’image pour avoir l’affichage d’un smiley. Il faut modifier le paramètre du bloc et choisir une image parmi les propositions:
Vous pouvez alors téléverser le programme dans la carte microbit et observer l’affichage. Il y a 2 options proposées:
Soit utiliser le bouton téléverser. Le programme se charge alors automatiquement dans la carte microbit
soit le bouton de téléchargement. C’est l’ordinateur qui charge alors le programme généré (l’extension est .hex). Il faudra le deplacer sur la carte microbit à l’aide de l’explorateur:
Ajouter une instruction conditionnelle (si le bouton A est préssé, alors…)
Si on met à nouveau les blocs en correspondance avec les instructions du langage, cela donne:
Qu1.: colorier le script sur la fiche de reponse.
Les instructions en python ne sont pas alignées sur la même verticale. On dit qu’elles sont indentées lorsqu’elles présentent un décalage horizontal. Cette disposition est aussi visible sur l’algorithme écrit en langage scratch (blocs colorés).
Qu2.: Expliquer la signification de cette indentation en Python
Terminer maintenant le programme selon l’image suivante:
Et téléverser dans la carte microbit. Comment réagit-elle lorsque vous appuyez sur le bouton A, le bouton B?
Qu3.: Comment la réagit la carte lorsque l’on appuie sur les 2 boutons simultanément? Cela génère t-il un bug a l’affichage? Pourquoi?
Modifier la structure conditionnelle en remplaçant la séquence: si … si …
Qu4.: Cela améliore t-il le comportement de la carte lorsque l’on appuie simultanément sur les 2 boutons? Pourquoi?
Introduction au langage Python
Le langage python, comme tout langage informatique est un langage très structuré, qui utilise un petit nombre de mots clés, à partir desquels on construit des instructions.
Les couleurs (programme en blocs, fenêtre de gauche) indiquent la famille d’instructions. Les instructions du langage peuvent être rassemblées selon les principales familles qui sont:
Affichage
Entrées/ Sorties
Logique
Boucles
Variables
D’autres familles d’instructions concernent la programmation de Fonctions, ou l’utilisation de types construits comme les chaines de caractères et les listes, les opérations Math, ou la gestion des erreurs (Exceptions).
Les fonctions Communication, Capteurs, Actionneurs, Robots, … concernent la manipulation d’objets technologiques et apportent des extensions du langage. Selon les besoins, il faudra parfois ajouter des extensions de cette sorte, comme ici avec la première ligne:
frommicrobitimport*
Avec la programmation par blocs sur l’interface Vittascience.com, cette ligne est ajoutée dès que vous choisissez une instruction du bloc Entrées/Sorties spécifique à la carte microbit.
Qu5.: compléter le tableau avec la description de l’instruction:
mot clé
description
import
display.show()
button_a.is_pressed()
button_b.is_pressed()
Les instructions qui terminent par des parenthèses () sont des fonctions. Les fonctions executent une série d’instructions, qui sont rassemblées dans un seul bloc appelé fonction. Cela permet de rendre le script plus court et plus lisible. Une fonction peut être réutilisée à plusieurs endroits du programme.
Parmi ces fonctions, certaines doivent être écrites en plaçant un argument entre les parenthèses. Cela permet de préciser leur comportement.
**Qu6.: Dans le tableau précédent, quelle est LA fonction qui nécessite un argument? A quoi sert-il?
Certaines instructions vont permettre des répétitions (famille des boucles), d’autres vont executer des branchements conditionnels (famille logique). Ce sont les mots clés while et if.
Qu7.: Retrouver les familles pour chacun de ces 2 mots clés, if et while. Préciser: lequel va servir pour une instruction conditionnelle, executée une seule fois? Lequel sert à répéter un bloc de code (écrire dans la colonne execution)?
mot clé
famille
execution
if
while
Qu8: compléter le tableau avec la description de chacune des instructions:
instruction
description
while True:
if button_a.is_pressed():
Dessiner son propre logo
Le bloc suivant permet de personnaliser l’image affichée:
Lorsque l’on ajoute ce bloc au programme, cela insère les 2 lignes suivantes dans le script python:
L’image est alors générée par la ligne led_image = Image('00000:00000:00000:00000:00000'). L’instruction display.show(led_image) va afficher cette image sur la carte microbit.
Remplacer les 2 images du programme précédent (smiley happy/sad). Placer vos propres dessins, réalisés à partir de la matrice.
Pour dessiner l’image, il faut cliquer dans les cellules de la matrice(pixels). Le bloc suivant affiche un Y sur la carte microbit.
Quel est le code correspondant pour le Y?
Programmez la carte afin qu’elle montre l’animation suivante:
rotation droite
Recopier le code python qui est généré -> Qu9.
Partie 2 : Projets utilisant le module radio
Envoyer un message par ondes radio
La carte microbit possède une antenne radio, ce qui lui permet d’emettre et de recevoir des messages.
communication radio en reseau
Projet 1: Animation à plusieurs cartes microbit
Utiliser le module radio de la carte microbit pour afficher un dessin glissant sur plusieurs cartes.
Il faudra synchroniser l’animation, afin de provoquer cet effet de glissement de l’image. Par exemple, déclencher l’animation sur la carte 2 lorsque le dessin sort de la carte 1.
Projet 2: Communication confidentielle
Vous allez envoyer un message dans le reseau de cartes.
L’une de ces cartes est une carte mystère. Celle-ci est programmée pour repondre lorsqu’elle reçoit le message “Hello”.
Vous cherchez à découvrir ce que la carte mystère va répondre. Aussi, vous allez programmer votre carte pour qu’elle emette le mot “Hello”, et qu’elle n’affiche que les mots différents de “Hello”: c’est à dire les messages qui proviennent de la carte mystère…
Voici le programme que vous devrez saisir:
programme complet
Dans le menu Variables, créer une nouvelle variable que vous nommerez n.
Créez 2 autres variables que vous nommerez texte et message.
Ajouter l’instruction Affecter à n la valeur " “.
Saisir une valeur numerique à 2 chiffres dans ce bloc. Ce sera votre identifiant. Cette valeur doit être unique, personne ne devra avoir la même parmi les autres cartes du reseau. (L’exemple suivant sera traité avec la valeur 19).
Ne pas choisir 19: ce nombre doit être différent pour chacune des cartes élèves de la classe.
Ajouter l’instruction Affecter à texte la valeur " “.
La variable n se trouve dans la liste des blocs du menu Variables
Ajouter la variable n dans ce bloc.
Ajouter alors les blocs suivants pour finir la partie Au demarrage:
Ces instructions permettent de construire la variable message par collage des 2 chaines de caractère, n et texte.
n='19'message=ntexte='Hello'message=message+texte
Un langage informatique utilise des variables. Ce sont des caractères ou des mots, qui n’existent pas dans le langage, et que vous choisissez pour y stocker une valeur. En langage Python, le signe ‘=’ devant une variable indique que l’on stocke la valeur de droite dans la variable ecrite à gauche:
jour='lundi'
Cette instruction signifie que l’on stocke le mot ’lundi’ dans la variable jour.
Question a: Quelles sont les variables utilisées dans ce programme?
Question b: Quelles chaines de caractères sont stockées dans les variables lors des 3 premieres instructions:
n='19'message=ntexte='Hello'
Question c: Quel est le contenu de la variable message apres la dernière instruction?
message=message+texte
Poursuivre la programmation:
Dans la partie Répéter indefiniment:
Ajouter les blocs qui permettront d’envoyer par radio la chaine message.
Remplacer le texte par la variable message
Ajouter les blocs qui vont traiter les messages radio reçus (s’il y en a):
Ajouter le bloc [radio] si une chaine est reçu dans stringData alors:
Puis, pour obtenir la condition si dans la chaine strigData obtenir la sous-chaine…, vous allez passer par les étapes suivantes:
choisir la variable stringData
Placer ce bloc dans l’instruction conditionnelle:
Rechercher l’instruction suivante dans le menu Textes:
il faudra probablement remplacer la variable proposée
Choisir la variable stringData
Choisir la sous-chaine depuis lapremiere lettre:
Dans le menu math, trouver le selecteur de valeur numerique:
mettre la valeur 1
Modifier le signe (mettre =) et compléter l’instruction avec la variable n:
Téléverser et tester le programme.
Question d: Vous devriez recevoir un message personnalisé de la carte microbit mystère. BRAVO!! Recopiez ce message.
Question e: Le programme utilise des instructions apportées par la librairie radio, utiles pour la programmation de la carte microbit.
Quel est le rôle des fonctions suivantes: Recopier et compléter le tableau:
instruction
description
send
receive
Question f: Quel est le rôle de la variable stringData? (Que contient-elle?)
Compléments: Configuration radio
radio.config(channel=7): Configure la fréquence d’émission : la valeur est un numéro entre 0 et 83
radio.config(group=0): Configure le groupe : au sein d’une même adresse, 256 groupes numérotés de 0 à 255 peuvent cohabiter`
Programme de la carte MB mystere
notes pour l’enseignant
Programme de la carte eleve
Correction à venir
Programme de la carte enseignant
frommicrobitimport*importradioimportutime"""
# chaque carte eleve recoit son propre message
# meme apres plusieurs appuis successifs sur le btn a
# son id est stocke dans le dict D
"""radio.on()radio.config(channel=7,power=6,length=32,group=0)i=0L=['mardi','juillet','but']# ...liste de mots mysteres a completerl=len(L)D={}n_precedent=0whileTrue:stringData=radio.receive()ifstringData:n=stringData[:2]ifn_precedent!=n:ifnnotinD.keys():D[n]=[L[i%l],3]message=stringData[:2]+" "+D[n][0]i+=1radio.send(message)utime.sleep(0.5)display.clear()# repere pour avoir le nombre de message retournesdisplay.set_pixel(i%5,(i%25)//5,9)n_precedent=nelifn_precedent==nandD[n][1]>0:# gestion d'un appui prolongéD[n][1]-=1elifn_precedent==nandD[n][1]<=0:D[n][1]=3n_precedent=0# RAZ du TTL et id precedent# on renvoie le mot
Une présentation générale de la carte microbit et des editeurs pour sa programmation se trouve à la page MB_init. Ce TP fait suite à celui de SNT, à la page MB radio.
La carte microbit possède une antenne radio, ce qui lui permet d’emettre et de recevoir des messages:
source: microbit.org
Prise en main de l’interface microbit sur Vittascience
Ce premier travail permet de découvrir l’interface Vittascience.com pour la programmation de la carte microbit. Les questions qui suivent cette manipulation vont permettre d’approfondir les connaissances en langage Python. Les projets qui complètent cette séquence se basent sur la partie RESEAUX du programme (protocole HTTP, securité des transmissions)
Ce programme, comment devrait-il fonctionner? Quel-s problème-s voyez-vous lorsque plusieurs cartes microbits fonctionnent de concert, avec ce même programme?
Pour communiquer à 2 cartes microbit, dans un reseau privé, vous pouvez choisir votre valeur pour radio.config(group=0), comme par exemple radio.config(group=1), … (maximum 255).
Choisir le-s terme-s adapté-s parmi les mots suivants: il s’agit d’un problème de…
intégrité
authenticité
confidentialité
Projet 1: Générateur de messages
But: On améliore le dispositif pour faire une selection parmi plusieurs messages (au moins 3). Les messages peuvent être des textes brefs, ou bien des messages de reaction de type LIKE/ UNLIKE.
discussion
Compléments théoriques: index modulo avec %
Cette fois, le nombre de messages possibles est supérieur au nombre de boutons (3 messages pour 2 boutons).
Nous allons utiliser une liste de messages. Pour acceder à un element de cette liste, nous allons utiliser un index. Exemple:
# declaration de la listeL=['mon message a envoyer','LIKE','UNLIKE']# acceder a l'un des elements de la liste:# 1er element: index 0print(L[0])# 2e element: index 1print(L[1])# 3e element: index 2print(L[2])# attention au depassement d'index de la liste# l'index 3 n'existe pasprint(L[3])
On peut utiliser un index numérique pour parcourir tous les éléments de la liste. Exemple:
On a alors une selection periodique des éléments de liste.
Programmation de la carte microbit
Utiliser maintenant l’interface Python sur Vittascience.com pour réaliser les modifications.
Bloc “Au démarrage”: régler les cartes par binome sur le même reseau (même canal, et même group).
Dans le bloc: Répéter indéfiniment (while True), il faudra modifier le rôle des boutons et le comportement lorsqu’un message est reçu.
rôle des boutons a et b
Bouton a
le bouton_a sert à selectionner le message dans une liste, en passant au message suivant dans la liste. L’indice est calculé selon une règle d’arithmétique modulaire. Voici un extrait du script à utiliser:
# a placer au "demarrage"L=['message','like','unlike']i=0...# a placer dans le bloc "repeter indefiniment"ifbutton_a.is_pressed():i=(i+1)%3...ifbutton_b.is_pressed():radio.send(L[i])
[En option] Ajout d’un repère visuel: On peut ajouter un repère visuel pour la selection du message. On éclaire alors la diode de la première ligne (y=0), dont la position x correspond à l’index x=i. Cela donne: display.set_pixel(i,0,9)
Les 2 autres instructions servent à effacer l’écran display.clear(), et à placer un délai d’attente utime.sleep(0.2), necessaire pour eviter de nombreux appuis prolongés sur le bouton.
Bouton b
Le bouton_b servira à envoyer le message.
ifbutton_b.is_pressed():radio.send(messages[i])
On pourra placer un repère visuel qui montre l’envoi du message:
elif, sinon si c’est ‘unlike’, on affiche un smiley triste
else, sinon, c’est un message textuel, on l’affiche avec display.scroll(stringData)
Vous avez reussi à échanger des messages avec votre binôme? Poursuivre cette séance avec les 2 projets suivants.
Projet 2: Auteurs authentifiés
But: Utiliser une règle d’authentification entre 2 cartes de votre réseau privé.
Votre reseau privé n’est pas à l’abris d’un utilisateur non invité. Vous souhaiteriez alors savoir de QUI vient le message reçu.
L’idée est d’utiliser la chaine de caractère émise pour y placer des informations, en plus du message. Ces informations pourraient identifier la carte émettrice. Ainsi, plutôt que d’envoyer:
"le lundi ne mange pas a la cantine"
la carte n°1 enverra:
"1_le lundi ne mange pas a la cantine"
Le programme recepteur pourra afficher la chaine de caractère entière, renseignant à la fois le numéro de la carte emettrice ET le message.
Pour lire le numéro au début du message, il faudra PARSER la chaine reçue. Parser signifie: diviser une chaîne de caractères en une liste ordonnée de sous-chaînes.
Dans un notebook (Atrium > Capytale) ou bien basthon.fr/, saisir les lignes suivantes:
Composer le message:
n=1texte="la feve est dans la 3e part"message=str(n)+"_"+texteprint(message)
Parser le message avec un Slice:
Il faudra tranformer la chaine "1_la feve est dans la 3e part" en 2 chaines: "1" et "la feve est dans la 3e part".
message="1_la feve est dans la 3e part"n=message[0]# selection du 1er caractereprint(n)# affiche: 1message=message[2:]# slice du 3e caractere au dernierprint(message)# affiche: la feve est dans la 3e part# on a extrait le numero au debut du message, et reduit le messageprint("la carte n°",n," vous informe que\n",message)
Ou mieux, parser le message avec la méthode de chaine split:
message="1_la feve est dans la 3e part"L=message.split('_')# L vaut ['1','la feve est dans la 3e part']n=L[0]message=L[1]
Pour traiter un message dont l’identifiant numérique est composé de 2 chiffres: Quelle méthode vaut-il mieux privilegier?
Programmation de la carte microbit
Adapter le programme pour permettre une communication avec un auteur authentifié dans un reseau à plusieurs cartes.
Vous allez mettre 2 cartes microbits ou plus dans un même réseau privé (Réglage dans l’instruction radio.config(channel = 7, power = 6, length = 32, group=0)). Choisir le même channel et le mêmegroup pour les cartes microbit du même groupe.
A partir du programme initial, apporter les modifications pour:
Choisir un numero pour votre groupe privé que vous placerez dans groupe_prive. Modifiez votre message à envoyer.
Ecrire une fonction parse qui prend en paramètre une chaine de caractère message, et un caractère de separation sep. Cette fonction doit retourner une liste L constituée de 2 éléments: L[0] contient le numero du groupe et L[1] le message placé après le caractère de séparation.
Ajouter à votre script la fonction test_parse() qui teste le bon fonctionnement de la fonction parse:
deftest_parse():assertparse("1_les carrotes sont cuites","_")==["1","les carrotes sont cuites"]assertparse("1_2_3","_")==["1","2"]
Ajouter aussi l’appel de la fonction parse_test() dans le corps de votre programme.
Lorsque l’on appuie sur le bouton b: envoyer un message avec un numero d’identification à 2 chiffres. Ce numero doit être le même pour toutes les cartes microbits du même reseau privé. Le message sera mis en forme avec str(groupe_prive) + "_" + message
parser et afficher tout message qui commence par le bon identifiant, pas les autres messages reçus. Il faudra utiliser une instruction conditionnelle sur le numéro de carte pour afficher (ou non) le message.
Votre script devrait avoir les instructions suivantes:
frommicrobitimport*importradioimportutimegroupe_prive=...radio.on()radio.config(channel=7,power=6,length=32,group=groupe_prive)message="message a personnaliser"# personnalisez votre messagedefparse(message,sep):"""retourne une liste constituée de 2 elements
decoupe de la chaine message autour du caractere sep
"""passdeftest_parse():assertparse("1_les carrotes sont cuites","_")==["1","les carrotes sont cuites"]assertparse("1_2_3","_")==["1","2"]test_parse()whileTrue:ifbutton_b.is_pressed():radio.send(...stringData=radio.receive()ifstringData:...
Tester le bon fonctionnement de votre programme dans un reseau contenant plusieurs cartes microbits. Décrivez le reseau (nombre de cartes microbit de chaque groupe et numeros de ces groupes).
Projet 3: Chiffrement
But: réaliser une communication privée dans un reseau public.
Premier programme utilisant un notebook python
Chiffrer / Code Cesar: Le code César réalise une permutation des caractères, selon leur rang (table ASCII), grâce à une clé de chiffrement/ déchiffrement.
Les fonctions utiles du langage sont: ord et chr:
>>>ord('a')97>>>chr(98)'b'>>>chr(122)'z'
Pour utiliser une clé de chiffrement, il sera nécessaire d’utiliser un décalage avec un modulo(26) afin d’obtenir une lettre chiffrée dans l’alphabet a-z:
no_lettre=ord(lettre)chiffre=no_lettre+cle# decalage sans modulo, depassement possiblechiffre=(lettre+cle)%26# decalage avec modulo 26, chiffre de 0 à 25chiffre=(lettre-97+cle)%26+97# decalage avec modulo 26, chiffre de 97 à (97 + 25) = 122
Comme l’alphabet a-z va du rang 97 à 122 dans la table ascii, on choisira la 3e méthode:
chiffre = (lettre-97 + cle)%26 + 97
Créer une fonction de chiffrement appelée chiffre, qui retourne la lettre chiffrée selon les arguments lettre (lettre en clair) et cle (la clé de chiffrement).
La fonction chiffre peut aussi servir à déchiffrer. Il suffira de remplacer la clé de chiffrement par son opposé: $3 => -3$.
Assurez vous à l’aide de quelques tests, que la fonction donne de bons résultats, pour chiffrer et dechiffrer un caractère.
Créer une fonction de chiffrement appelée chiffre_texte, qui retourne la texte chiffré. La fonction aura pour arguments: texte (texte en clair) et cle (la clé de chiffrement).
Assurez vous à l’aide de quelques tests, que la fonction donne de bons résultats, pour chiffrer et dechiffrer un texte.
Comment pourrait-on réaliser un reseau mesh pour la ville de Nice? Expliquer ce qu’il faudrait utiliser en terme de matériel, de noeuds du reseau, ainsi qu’en terme de logiciels, pour assurer l’intégrité et la confidentialité.
Une présentation générale de la carte microbit et des editeurs pour sa programmation se trouve à la page MB_init. Ce TP fait suite à celui de 1ere NSI, à la page MB radio2.
La carte microbit possède une antenne radio, ce qui lui permet d’emettre et de recevoir des messages:
source: microbit.org
Prise en main de l’interface microbit sur Vittascience
Ce premier travail permet de découvrir l’interface Vittascience.com pour la programmation de la carte microbit. Les questions qui suivent cette manipulation vont permettre d’approfondir les connaissances en langage Python. Les projets qui complètent cette séquence se basent sur la partie RESEAUX du programme (protocole HTTP, securité des transmissions)
Quel est la signification de chacune des instructions suivantes?
instruction
description
if stringData:
if stringData == 'LIKE':
Le programme utilise des instructions apportées par les librairies radio et utime, utiles pour la programmation de la carte microbit.
Quel est le rôle des fonctions suivantes: Recopier et compléter le tableau:
instruction
description
send
receive
sleep
Quel est le rôle de la variable stringData? (Que contient-elle?)
Selection de message:
Expliquez le rôle des instructions suivantes:
l=len(messages)i=(i+1)%l
Analyse du programme: Décrire le programme avec un diagramme d’activités (exemple à la page 4).
Ce programme, comment devrait-il fonctionner? Quel-s problème-s voyez-vous lorsque plusieurs cartes microbits fonctionnent de concert, avec ce même programme?
Choisir le-s terme-s adapté-s parmi les mots suivants: il s’agit d’un problème de…
intégrité
authenticité
confidentialité
Programmation orientée objet
On souhaite effacer du programme les variables globales. Les variables seront regroupées comme attributs de la classe Communication_radio. On ajoutera à cette classe les méthodes qui serviront à rendre le script plus concis.
Voici le script que vous allez utiliser: Créer un nouveau fichier, coller ce nouveau script et complétez le pour qu’il soit fonctionnel.
frommicrobitimport*importradioimportutimeclassCommunication_radio:def__init__(self,# a completer)# a completerdefmessage_suivant(self):# a completerdefselect_message(self):# a completerdefimg_send(self):# a completercom=Communication_radio(7,0,['lundi','LIKE','UNLIKE'])radio.on()radio.config(channel=com.channel,power=6,length=32,group=com.group)whileTrue:ifbutton_a.is_pressed():com.message_suivant()ifbutton_b.is_pressed():radio.send(com.select_message())com.img_send()# affiche l'animation lors de l'envoi du messagestringData=radio.receive()ifstringData:ifstringData=='LIKE':display.show(Image.HAPPY)utime.sleep(0.2)display.clear()elifstringData=='UNLIKE':display.show(Image.SAD)utime.sleep(0.2)display.clear()else:display.scroll(stringData)
Question: quelles sont les différentes méthodes que vous pouvez envisager pour que la communication entre 2 cartes microbit reste confidentielle?
Projets
Poursuivre cette séance avec les 2 projets suivants.
But: réaliser une communication privée dans un reseau public.
Premier programme utilisant un notebook python
Chiffrer / Code Cesar: Le code César réalise une permutation des caractères, selon leur rang (table ASCII), grâce à une clé de chiffrement/ déchiffrement.
Les fonctions utiles du langage sont: ord et chr:
>>>ord('a')97>>>chr(98)'b'>>>chr(122)'z'
Pour utiliser une clé de chiffrement, il sera nécessaire d’utiliser un décalage avec un modulo(26) afin d’obtenir une lettre chiffrée dans l’alphabet a-z:
no_lettre=ord(lettre)chiffre=no_lettre+cle# decalage sans modulo, depassement possiblechiffre=(lettre+cle)%26# decalage avec modulo 26, chiffre de 0 à 25chiffre=(lettre-97+cle)%26+97# decalage avec modulo 26, chiffre de 97 à (97 + 25) = 122
Comme l’alphabet a-z va du rang 97 à 122 dans la table ascii, on choisira la 3e méthode:
chiffre = (lettre-97 + cle)%26 + 97
Créer une fonction de chiffrement appelée chiffre, qui retourne la lettre chiffrée selon les arguments lettre (lettre en clair) et cle (la clé de chiffrement).
La fonction chiffre peut aussi servir à déchiffrer. Il suffira de remplacer la clé de chiffrement par son opposé: $3 => -3$.
Assurez vous à l’aide de quelques tests, que la fonction donne de bons résultats, pour chiffrer et dechiffrer un caractère.
Créer une fonction de chiffrement appelée chiffre_texte, qui retourne la texte chiffré. La fonction aura pour arguments: texte (texte en clair) et cle (la clé de chiffrement).
Assurez vous à l’aide de quelques tests, que la fonction donne de bons résultats, pour chiffrer et dechiffrer un texte.
Adapter le programme pour permettre une communication confidentielle entre 2 cartes microbit. Décrire le programme avec un diagramme d’état.
Projet 3: Compteur de likes
Programme
On considère le réseau social de type “X (ex Twitter)” dans lequel A, B, C, et D sont des usagers (des twittos)
A suit B
B suit C
C suit A et B
D suit B
La structure de données sera un dictionnaire Python:
# un exemple de dictionnaire représentant un graphe à 4 cartesG={'A':['B'],'B':['C'],'C':['A','B'],'D':['B']}
Vous allez expérimenter la chaine de messages dans ce réseau social.
Chaque twittos envoie, régulièrement, un message sur le reseau:
Ce message contient pour unique contenu le mot Publi. L’émetteur du message devra s’identifier lorsqu’il fait une publi:
# pour le twittos Bradio.send("B_Publi")
Lorsque A reçoit un message de B (c’est à dire le message qui commence par "B"): comme "B" est dans sa liste self.reseau['A'], A envoie un like à B. (un message “B_LIKE”`). Et affiche un smiley HAPPY:
Si B reçoit le message "B_LIKE". Il verifie que le premier caractère n correspond à son propre numero de carte (n == self.numero). il affiche un COEUR, puis la valeur de son compteur, incrémentée de 1.
Démarrer le programme de manière synchrone sur chaque carte microbit du reseau. Faites une publication de manière régulière (chronométer). Expérimenter pendant 2 à 5 minutes, puis relever les valeurs des compteurs sur chaque carte.
Les valeurs sont-elles en accord avec la structure du reseau?
Redigez une description de votre programme, de votre experimentation, ainsi qu’un commentaire des résultats.
Aide
On utilisera la classe:
classCommunication_radio:def__init__(self,ch=7,gpe=0,messages=['LIKE','Publi'],numero='A',reseau={'A':['B'],'B':['A']}):self.channel=chself.group=gpeself.messages=messagesself.img=[Image.DIAMOND,Image.DIAMOND_SMALL]self.numero=numeroself.reseau=reseauself.compteur=0defselect_message(self):message_complet=str(self.numero)+"_"+self.messages[1]returnmessage_completdefimg_send(self):display.show(self.img,delay=100)utime.sleep(0.015)display.clear()defparse(self,stringData):"""decoupage de stringData en une chaine n ('A, 'B', ...)
et un texte grace a la methode split('_')
returns:
--------
- etat du compteur +1 si n == self.numero ET texte == 'LIKE'
- 'LIKE' si n est le numero d'un compte suivi ET texte == 'Publi'. Et emission radio avec radio.send('n_LIKE')
- '', string vide, si n ne correspond a aucun des 2 cas precedents
"""# a completer
Le travail demandé consiste alors à compléter la méthode de classe parse. Il est conseillé de bien comprendre la correction du Projet 1 avant de commencer: Solution du projet_authentifier_POO.py
Après l’import des librairies, et la déclaration de la classe Communication_radio, le programme sera le suivant:
# Attention a changer le 4e argument par la lettre attribuee a votre carte ('A', 'B', ...)# modifier aussi le reseau {'A':['B'],'B':['A']} si vous avez plus# de 4 cartescom=Communication_radio(7,0,['LIKE','Publi'],'B',{'A':['B'],'B':['A']})radio.on()radio.config(channel=com.channel,power=6,length=32,group=com.group)whileTrue:ifbutton_a.is_pressed():radio.send(com.select_message())com.img_send()# affiche l'animation lors de l'envoi du messagestringData=radio.receive()ifstringData:texte=com.parse(stringData)iftexte=='LIKE':display.show(Image.HAPPY)utime.sleep(0.4)display.clear()else:display.scroll(texte)utime.sleep(0.4)display.clear()
Programmer un robot a pour but de lui faire réaliser des tâches autonomes, répétitives. Il va prendre des décisions en fonction de son environnement grâce à un algorithme.
Selon la tâche à executer, il faudra bien distinguer les instructions que le robot n’execute qu’une seule fois, et celles qu’il devra répéter indéfiniment.
disposer les instruction dans le bon bloc de code
Défi n°1: S’arrêter au parking
Le robot peut être prévu pour circuler selon une couleur marquée au sol.
les différentes fonctions d’actions des moteurs sont dans le menu Robots de la page de l’editeur Vittascience.com
Le menu Robots propose les instructions de plusieurs robots. Le votre s’appelle Maqueen.
[Maqueen] Contrôler le robot avancer vitesse 50
la valeur de vitesse est un paramètre ajustable. Mettre 50
[Maqueen] Arrêter le robot
Dans le menu Entrees/Sorties, choisir le bloc attendre 1 seconde-s, et réaliser le programme suivant:
Tester ce premier programme avec le robot maqueen. Puis démarrer un nouveau projet pour stopper le robot dans une zone noire.
Pour ce défi:
Votre programme utilise une structure conditionnelle: retrouvez celle-ci dans le menu logique.
Le robot dispose de 2 capteurs d’intensité lumineuse, sous le chassis.
La mesure de l’état du capteur de ligne, sous le robot se fait grâce à la fonction:
[Maqueen] Etat du capteur ligne droit / gauche
Cette instruction renvoie un booléen (True, False), qui sera affectée à une variable. Créez 2 nouvelles variables, G et D.
Affecter les instructions des capteurs de ligne à chacune de ces variables:
On place alors ces variables dans une structure conditionnelle (si G ET D faire…):
Si le capteur G vaut True et le capteur D vaut True: avancer
à vous de jouer: Créez un programme qui fait avancer le robot tant qu’il est sur une piste blanche. Et qui s’arrête lorsqu’il est sur son parking, noir.
Vous avez reussi?
Sauvegardez le programme dans vos documents.
Et recopier le script sur votre cahier.
Défi n°2: Suivi de ligne
Le robot peut circuler en suivant une courbe peinte au sol.
Une différence de clarté sous le robot (bord du chemin) permet de programmer un virage du robot.
Il faudra alors placer les instructions de commande du moteur Droit et Gauche dans une sequence d’intructions conditionnelles.
if
...
elif
...
else
Pour faire pivoter le robot, il faudra contrôler différement chaque moteur (Droit / Gauche). Utiliser:
[Maqueen] Contrôler le moteur gauche direction … vitesse 50
à vous de jouer: Créer un deuxième programme qui fera:
tourner le robot vers la droite lorsqu’il se trouve dans la situation suivante:
blanc/noir => virage a droite
tourner vers la gauche dans la situation inverse
sinon: avancer tout droit lorsque les 2 capteurs mesurent la même couleur noire, ou blanche.
Tester alors votre programme sur une piste circulaire.
Votre robot fait le tour entierement? Vous avez relevé le premier défi!
Travail: Recopier le script python dans un fichier .txt
D’autres fonctions du robot peuvent être exploitées pour réaliser d’autres tâches. Par exemple:
[Maqueen] Pivoter à droite
[Maqueen] Avancer d’une case
Pour la suite, il sera utile de partir du programme réalisé avec les blocs (Vittascience), puis d’adapter, modifier certains paramètre à la main, directement dans le script python.
Vous devrez vous familiariser avec les instructions en python spécifiques au robot marqueen.
Editeur Vittascience.com. Placer l’une des commandes du robot dans le bloc “Au demarrage”. Et lire le script python généré.
Travail: Copiez le contenu du document maqueen.py. Coller les instructions dans votre fichier .txt. Et complétez le avec les instructions python des différents blocs.
Certaines commandes necessitent la declaration de fonctions, et occupent plusieurs lignes d’instructions.
Défi n°3: Avancer d’une case
Pour programmer les deplacements du robot indépendemment du marquage au sol, il sera necessaire de calibrer la longueur de ses deplacements.
Ouvrir un nouveau projet et mettre dans le bloc “Au demarrage”, l’instruction “avancer d’une case”. La longueur parcourue correspond-elle à la dimension d’une case sur le support?
Les paramètres doivent être ajustés dans le script python (blocs inopérants pour ajustements).
La longueur du deplacement dépend de la durée d’attente utime.sleep_ms(int(15e-2/speed_mps*1000)) dans la fonction maqueen_moveWithSquare.
Passer en mode programmation python. Ne plus revenir sur l’interface avec les blocs. Modifier le script python et tester avec le robot. Quelle(s) modification(s) lui permet(ent) d’avancer d’une case sur le support?
De la même manière, il sera utile de calibrer l’angle de rotation lors de la commande de pivot à droite ou à gauche.
Travail: Créer le programme qui permet au robot de suivre un chemin proposé, comme sur l’image plus haut. Utiliser une LISTE python comme structure de données pour placer les consignes de parcours (ex: chemin = [1,1,1,2,1,1,2,1,1,3,1]). Ce parcours doit utiliser les cases du support.
Recopier le script dans votre fichier .txt
Défi 4: Enregister des données
L’enregistrement de données peut être utile pour calibrer les capteurs du robot.
Le programme suivant peut être chargé dans l’interface Vittascience.com. Télécharger le fichier. Puis l’ouvrir depuis l’interface.
La fonction getUltrasonicData permet de mesurer une distance/un temps selon le paramètre data.
Pour écrire des données sur la carte, ce sont les fonctions:
log.set_labels: definition des colonnes du tableau de mesure
log.add pour ajouter une entrée dans le tableau
On utilisera alors l’explorateur (windows) pour ouvrir et visualiser les données, dans un fichier d’extension .html
frommicrobitimport*importlogimportutimefrommachineimporttime_pulse_us""" Maqueen robot """# Ultrasonic TRIG on pin1# Ultrasonic ECHO on pin2defgetUltrasonicData(trig,echo,data='distance',timeout_us=30000):trig.write_digital(0)utime.sleep_us(2)trig.write_digital(1)utime.sleep_us(10)trig.write_digital(0)echo.read_digital()duration=time_pulse_us(echo,1,timeout_us)/1e6# t_echo in secondsifduration>0:ifdata=='distance':#sound speed, round-trip/2, get in cmreturn343*duration/2*100elifdata=='duration':returndurationelse:raiseValueError("Data option '"+data+"' is not valid")else:return-1log.set_labels('distance',timestamp=log.MILLISECONDS)log.set_labels('temps',timestamp=log.MILLISECONDS)i=0whileTrue:ifbutton_a.is_pressed():log.delete(full=True)i=0utime.sleep(1)d=getUltrasonicData(pin1,pin2,'distance')ifd>0:log.add(distance=d,temps=i)i=i+1display.scroll(str(d),delay=150,wait=True)
Le format des données dans le fichier de log permet un traitement comme on le ferait pour un ficher txt ou csv.
Suggestion de projets
Piloter le robot à l’aide d’une telecommande: on utilisera une 2e carte microbit pour telecommande. Les données seront transmises grâce à la fonction radio
Conduite autonome: le robot est capable d’avancer, et de s’arrêter seul lorsqu’il detecte un obstacle.
Course déclenchée par un clap
Evolution dans un labyrinthe
Programme d’exploration type robot aspirateur
Detection de formes (la forme de l’arêne dans laquelle est le robot)
Avec quelques extensions, les actions du robot peuvent être complexifiées (detection de couleur, ramassage d’objets, …).
Supports de tracés pour le robot
Documents pdf pour le robot suiveur de ligne: Lien vers pdf
Ce mini projet sera l’occasion de mettre en oeuvre les notions vues dans le cours précédent sur :
la définition d’un objet en javascript la gestion des évènements l’utilisation d’une fonction callback avec un timer Vous pourrez également suivre ce tutoriel avec la video à l’adresse : lien video Afficher des éléments en javascript Contenu du dossier du projet D’abord, créer un dossier contenant :
Le DOM le DOM ou Document Object Model, une interface qui fait partie du BOM (Browser Object Model) et grâce à laquelle nous allons pouvoir manipuler le contenu HTML et les styles de nos pages.
Le DOM est ainsi une représentation structurée du document sous forme « d’arbre » crée automatiquement par le navigateur, à partir de sa lecture du document HTML.
Algorithme des k plus proches voisins notebook Le notebook présenté ici se trouve à l’adresse tix06.github.io/jupyterlite_NSI
Choisir le dossier TP4_data_analyse puis le notebook algoKNN.ipynb.
Notebooks associés algorithme de recherche de plus proches voisins KNN: algKnn algorithme de recommandation : algorithme de recommandation.md arbres de décision : graphes_mini_prog.md Intelligence artificielle (IA) L’intelligence artificielle désigne des algorithmes plus ou moins évolués qui traitent des problèmes dont la résolution fait appel à l’intelligence humaine. Ils imitent des actions humaines.
Algorithmes de recommandation Lien vers le notebook en ligne : https://mybinder.org/v2/gh/tix06/notebooks_classif/master
Choisir alors le fichier : algorithme de recommandation.ipynb
Il s’agit d’un cas très classique d’algorithme utilisé dans le web marketing. Un client choisit et met dans ses favoris un article, ou dans son panier. Le site lui propose des articles compatibles, ou similaires. La recommandation peut être basée sur la description de ces articles. L’algorithme va alors chercher les articles qui ont le plus de points communs dans leur description; c’est à dire le plus de mots communs dans leur description.
Arbres de classification Lien vers le notebook en ligne : https://mybinder.org/v2/gh/tix06/notebooks_classif/master
Choisir alors le fichier : graphes_mini_prog.ipynb
Définition Un arbre de classification est utile pour réaliser des prévisions de manière explicite. C’est un outil utilisé
pour les algorithmes de backtracking (modéliser une partie d’echecs) pour l’appentissage automatisé (machine learning) supervisé (les classes des entrées sont connue) Pour le machine learning l’arbre peut évoluer et se restructurer à partir d’informations reçues.
tracer un arbre à partir d’une expression NPI NPI : notation polonaise inversée
En particulier : on dispose d’une expression en NPI, du type :
L3 = [7,8,’-’,6,’’,10,3,’+’,’’]
Et on veut créer et afficher le graphe correspondant : On utilisera le script :
L3 = [7,8,’-’,6,’’,10,3,’+’,’’] D = makeTree(L3) G = nx.Graph() graphDict(D) Dont l’instruction suivante va générer le dictionnaire à partir de l’expression NPI (fonction npiTree recursive):
Python : la librairie pandas notebook Le notebook présenté ici est à télécharger à l’adresse suivante :
https://mybinder.org/v2/gh/tix06/notebook_datas.git/master
Puis choisir : gestionBase_de_donnees_python.ipynb
Exercez vous en suivant le tutoriel avec ce notebook.
tracé de graphes avec Networkx Les scripts suivants permettent de choisir entre plusieurs types de configuration pour tracer un graphe avec Networkx, module Python.
On pourra choisir de personaliser :
la couleur d’un noeud l’etiquette des noeuds l’étiquette des arêtes le type de trait (plein ou en pointillés) des arêtes Déclaration du graphe import matplotlib.pyplot as plt import networkx as nx from numpy import array G = nx.Graph() # definition des noeuds G.add_node(0,label=‘A’,col=‘pink’) G.add_node(1,label=‘B’,col=‘red’) G.add_node(2,label=‘C’,col=‘white’) G.add_node(3,label=‘D’,col=‘white’) G.add_node(4,label=‘E’,col=‘white’) G.add_node(5,label=‘F’,col=‘blue’) # definition des aretes G.add_edge(0,1,weight=6,styl=‘dashed’) G.add_edge(0,2,weight=5,styl=‘solid’) G.add_edge(0,4,weight=1,styl=‘solid’) G.add_edge(4,1,weight=5,styl=‘solid’) G.add_edge(4,2,weight=1,styl=‘solid’) G.add_edge(4,3,weight=3,styl=‘solid’) G.add_edge(2,3,weight=8,styl=‘solid’) G.add_edge(4,5,weight=6,styl=‘dashed’) G.add_edge(3,5,weight=9,styl=‘solid’) Exploration de la structure de données couleur des noeuds liste = list(G.nodes(data=‘col’)) colorNodes = {} for noeud in liste: colorNodes[noeud[0]]=noeud[1] colorNodes {0: ‘pink’, 1: ‘red’, 2: ‘white’, 3: ‘white’, 4: ‘white’, 5: ‘blue’} Pour les couleurs des noeuds, le format doit être en liste (de la taille du nombre de noeuds)
Créer et resoudre un labyrinthe Les scripts suivants permettent de créer un labyrinthe de manière aléatoire, et d’exploiter la structure de données de ce labyrinthe. On pourra ainsi tester quelques algorithmes relatifs au parcours de ce labyrinthe. Les scripts en permettent une visualisation.
Définitions des classes class Pile: def init(self): self.lst = [] def empty(self): return self.lst == [] def push(self, x): self.lst.append(x) def pop(self): if self.empty(): raise ValueError(“pile vide”) return self.lst.pop() def explorer(laby): pile = Pile() pile.push((0, laby.q - 1)) laby.tab[0][laby.q - 1].etat = False while True: i, j = pile.pop() if i == laby.p - 1 and j == 0: break if j > 0 and laby.tab[i][j].S and laby.tab[i][j-1].etat: pile.push((i, j)) pile.push((i, j-1)) laby.tab[i][j-1].etat = False elif i < laby.p-1 and laby.tab[i][j].E and laby.tab[i+1][j].etat: pile.push((i, j)) pile.push((i+1, j)) laby.tab[i+1][j].etat = False elif j < laby.q-1 and laby.tab[i][j].N and laby.tab[i][j+1].etat: pile.push((i, j)) pile.push((i, j+1)) laby.tab[i][j+1].etat = False elif i > 0 and laby.tab[i][j].W and laby.tab[i-1][j].etat: pile.push((i, j)) pile.push((i-1, j)) laby.tab[i-1][j].etat = False return pile.lst class Case: def init(self): self.N = False self.W = False self.S = False self.E = False self.etat = False class Labyrinthe: def init(self, p, q): self.p = p self.q = q self.tab = [[Case() for j in range(q)] for i in range(p)] def show(self): plt.plot([0, 0, self.p, self.p, 0], [0, self.q, self.q, 0, 0], linewidth=2) for i in range(self.p-1): for j in range(self.q): if not self.tab[i][j].E: plt.plot([i+1, i+1], [j, j+1], ‘b’) for j in range(self.q-1): for i in range(self.p): if not self.tab[i][j].N: plt.plot([i, i+1], [j+1, j+1], ‘b’) plt.axis([-1, self.p+1, -1, self.q+1]) plt.show() def solution(self): sol = explorer(self) X, Y = [], [] for (i, j) in sol: X.append(i+.5) Y.append(j+.5) X.append(self.p-.5) Y.append(.5) plt.plot(X, Y, ‘r’, linewidth=2) self.show() def creation(p, q): laby = Labyrinthe(p, q) pile = Pile() i, j = randint(p), randint(q) pile.push((i, j)) laby.tab[i][j].etat = True while not pile.empty(): i, j = pile.pop() v = [] if j < q-1 and not laby.tab[i][j+1].etat: v.append(‘N’) if i > 0 and not laby.tab[i-1][j].etat: v.append(‘W’) if j > 0 and not laby.tab[i][j-1].etat: v.append(‘S’) if i < p-1 and not laby.tab[i+1][j].etat: v.append(‘E’) if len(v) > 1: pile.push((i, j)) if len(v) > 0: c = v[randint(len(v))] if c == ‘N’: laby.tab[i][j].N = True laby.tab[i][j+1].S = True laby.tab[i][j+1].etat = True pile.push((i, j+1)) elif c == ‘W’: laby.tab[i][j].W = True laby.tab[i-1][j].E = True laby.tab[i-1][j].etat = True pile.push((i-1, j)) elif c == ‘S’: laby.tab[i][j].S = True laby.tab[i][j-1].N = True laby.tab[i][j-1].etat = True pile.push((i, j-1)) else: laby.tab[i][j].E = True laby.tab[i+1][j].W = True laby.tab[i+1][j].etat = True pile.push((i+1, j)) return laby Librairies from numpy.random import randint import matplotlib.pyplot as plt Un premier exemple laby = creation(6, 5) laby.solution()
Utiliser le module turtle Le script suivant présente les classes et fonctions utiles pour :
tracer un labyrinthe complet parcourir le labyrinthe selon une méthode de parcours en profondeur tracer ce parcours animé avec turtle Utilisation :
tab=labyrinthe(5,6) L = parcours((len(tab)-1,0),(0,len(tab[0])-1),tab) afficheTurtle(tab,L) librairies from numpy.random import randint import matplotlib.pyplot as plt import turtle classes utiles class Pile: def init(self): self.lst = [] def empty(self): return self.lst == [] def push(self, x): self.lst.append(x) def pop(self): if self.empty(): raise ValueError(“pile vide”) return self.lst.pop() """ def explorer(laby): pile = Pile() pile.push((0, laby.q - 1)) laby.tab[0][laby.q - 1].etat = False while True: i, j = pile.pop() if i == laby.p - 1 and j == 0: break if j > 0 and laby.tab[i][j].S and laby.tab[i][j-1].etat: pile.push((i, j)) pile.push((i, j-1)) laby.tab[i][j-1].etat = False elif i < laby.p-1 and laby.tab[i][j].E and laby.tab[i+1][j].etat: pile.push((i, j)) pile.push((i+1, j)) laby.tab[i+1][j].etat = False elif j < laby.q-1 and laby.tab[i][j].N and laby.tab[i][j+1].etat: pile.push((i, j)) pile.push((i, j+1)) laby.tab[i][j+1].etat = False elif i > 0 and laby.tab[i][j].W and laby.tab[i-1][j].etat: pile.push((i, j)) pile.push((i-1, j)) laby.tab[i-1][j].etat = False return pile.lst """ class Case: def init(self): self.N = False self.W = False self.S = False self.E = False self.etat = False class Labyrinthe: def init(self, p, q): self.p = p self.q = q self.tab = [[Case() for j in range(q)] for i in range(p)] def show(self): plt.plot([0, 0, self.p, self.p, 0], [0, self.q, self.q, 0, 0], linewidth=2) for i in range(self.p-1): for j in range(self.q): if not self.tab[i][j].E: plt.plot([i+1, i+1], [j, j+1], ‘b’) for j in range(self.q-1): for i in range(self.p): if not self.tab[i][j].N: plt.plot([i, i+1], [j+1, j+1], ‘b’) plt.axis([-1, self.p+1, -1, self.q+1]) plt.show() """ def solution(self): sol = explorer(self) X, Y = [], [] for (i, j) in sol: X.append(i+.5) Y.append(j+.5) X.append(self.p-.5) Y.append(.5) plt.plot(X, Y, ‘r’, linewidth=2) self.show() """ def creation(p, q): laby = Labyrinthe(p, q) pile = Pile() i, j = randint(p), randint(q) pile.push((i, j)) laby.tab[i][j].etat = True while not pile.empty(): i, j = pile.pop() v = [] if j < q-1 and not laby.tab[i][j+1].etat: v.append(‘N’) if i > 0 and not laby.tab[i-1][j].etat: v.append(‘W’) if j > 0 and not laby.tab[i][j-1].etat: v.append(‘S’) if i < p-1 and not laby.tab[i+1][j].etat: v.append(‘E’) if len(v) > 1: pile.push((i, j)) if len(v) > 0: c = v[randint(len(v))] if c == ‘N’: laby.tab[i][j].N = True laby.tab[i][j+1].S = True laby.tab[i][j+1].etat = True pile.push((i, j+1)) elif c == ‘W’: laby.tab[i][j].W = True laby.tab[i-1][j].E = True laby.tab[i-1][j].etat = True pile.push((i-1, j)) elif c == ‘S’: laby.tab[i][j].S = True laby.tab[i][j-1].N = True laby.tab[i][j-1].etat = True pile.push((i, j-1)) else: laby.tab[i][j].E = True laby.tab[i+1][j].W = True laby.tab[i+1][j].etat = True pile.push((i+1, j)) return laby autres definitions utiles def directions(laby,i,j): “““les directions possibles pour la case courante i : int numero de ligne j : numero de la colonne retourne une liste (tuple) des points cardinaux possibles "”” L = [] if laby.tab[j][i].N == True: L.append(‘N’) if laby.tab[j][i].S == True: L.append(‘S’) if laby.tab[j][i].E == True: L.append(‘E’) if laby.tab[j][i].W == True: L.append(‘W’) return tuple(L) def labyrinthe(lines,col): "”" Params : ——– lines : int : nombre de lignes du labyrinthe col : int : nombre de colonnes Returns : ——— tab2 : list : tuples de 1 à 4 éléments correspondants aux directions libres (‘N’, ‘S’, E’, ‘W’) sortie : tracé du labyrinthe Variables : ———– p : nombre de colonnes (=largeur) q : nombre de lignes (=hauteur) """ laby = creation(col, lines) tab2 = [[0]laby.p for i in range(laby.q)] for i in range(laby.q): for j in range(laby.p): tab2[i][j] = directions(laby,i,j) Labyrinthe.show(laby) return tab2 def nexto(c,direc): “““retourne les coordonnées lors du deplacement selon la position actuelle et la direction Params : ——– c : tuple (ligne,colonne) correspondant à (y,x) dans le plan cartesien direct : str : ‘N’, ‘S’, E’, ‘W’ Returns : ——— tuple : (int,int) correspondant à (ligne,colonne) "”” i,j = c[0],c[1] if direc==‘N’ : return (i+1,j) if direc==‘S’ : return (i-1,j) if direc==‘E’ : return (i,j+1) if direc==‘W’ : return (i,j-1) def visited(c,L,couleur): “““retourne la couleur du noeud de coord c et de liste de directions possibles L selon celle de ses voisins Params : ——– c : tuple : (ligne,colonne) correspondant à (y,x) dans le plan cartesien L : list : tuples de 1 à 4 éléments correspondants aux directions libres (‘N’, ‘S’, E’, ‘W’) couleur : List dimension 2 contenant des elements str ‘white’ si noeud non visité, ‘green’ si le noeud est en cours de visite, ‘red’ si tous les noeuds ont été visités autour de lui Returns : ——— couleur : str : ‘green’ si le noeud est en cours de visite, ‘red’ si tous les noeuds ont été visités autour de lui "”” i,j = c[0],c[1] coul=‘red’ for direc in L: coord = nexto(c,direc) if couleur[coord[0]][coord[1]]‘white’:coul=‘green’ #print(c,coul) return coul def parcours(start,end,tab): “““trouve la solution au labyrinthe et trace ce chemin p : Pile() utile pour la recherche du parcours pchemin : Pile() utile pour memoriser tout le chemin on insère dans le chemin toutes les arêtes empruntées : pour le chemin entre c1 et c2, on insère c1 puis c2 "”” p = Pile() pchemin = Pile() p.push(start) c = start couleur = [[‘white’]*len(tab[0]) for i in range(len(tab))] while (not p.empty()) and (not c == end): c = p.pop() pchemin.push(c) # chaque fois que l’on depile, on rempile dans pchemin L = tab[c[0]][c[1]] couleur[c[0]][c[1]]=visited(c,L,couleur) # c est retiré de la pile et coloré en green ou red for direc in L: coord = nexto(c,direc) if couleur[coord[0]][coord[1]]‘white’: # le noeud fils est coloré en blanc dans la direction D p.push(c) # on remet le noeud parent afin de reconsidérer sa couleur à chaque fois que l’on depile # et le chemin arriere CONTINU pour le tracé p.push(coord) # alors on ajoute le noeud fils dans la direction D au sommet de la pile return pchemin.lst fonctions particulières au module turtle def turtleWall(dir,i,j): “““trace les murs des directions fermées dir est un tuple contenant les directions libres "”” larg = len(tab[0]) haut = len(tab) fenX = 600 fenY = fenXhaut/larg scaleX = (fenX-20)/larg scaleY = (fenY-20)/haut x0=-fenX/2+10 y0=-fenY/2+10 if not(‘N’ in dir[i][j]) : turtle.penup() turtle.setpos(x0+jscaleX,y0+(i+1)scaleY) turtle.setheading(0) turtle.pendown() turtle.forward(scaleX) if not(‘S’ in dir[i][j]) : turtle.penup() turtle.setpos(x0+jscaleX,y0+iscaleY) turtle.setheading(0) turtle.pendown() turtle.forward(scaleX) if not(‘E’ in dir[i][j]) : turtle.penup() turtle.setpos(x0+(j+1)scaleX,y0+iscaleY) turtle.setheading(90) turtle.pendown() turtle.forward(scaleY) if not(‘W’ in dir[i][j]) : turtle.penup() turtle.setpos(x0+jscaleX,y0+iscaleY) turtle.setheading(90) turtle.pendown() turtle.forward(scaleY) def turtleLab(tab): for i in range(len(tab)): for j in range(len(tab[i])): turtleWall(tab,i,j) #plt.plot([0, 0, len(tab[0]), len(tab[0]), 0], [0, len(tab), len(tab), 0, 0], ‘blue’,linewidth=10) #plt.savefig(’laby.png’) def turtlePath(tab,L): “““tracé du parcours dans le labyrinthe à l’aide de la tortue Params: ——- tab : Liste de liste contenant des str : ‘N’,‘S’,‘W’,‘E’ = le labyrinthe L : Liste de tuples correspondant aux cases visitées sortie : ——– le dessin du parcours animé "”” larg = len(tab[0]) haut = len(tab) fenX = 600 fenY = fenXhaut/larg scaleX = (fenX-20)/larg scaleY = (fenY-20)/haut x0=-fenX/2+10 y0=-fenY/2+10 turtle.penup() turtle.pencolor(“red”) turtle.setpos(x0+scaleX/2,y0+scaleY4+scaleY/2) # depart turtle.showturtle() turtle.pendown() start = L[0] for c in L[1:]: #angle = 90*(c[0]-start[0]) # si deplacement uniquement vertical if c[0]!=start[0] : depl = scaleY # vertical angle = 90*(c[0]-start[0]) else : depl = scaleX # horizontal angle = 90 - 90*(c[1]-start[1]) if c[1]<start[1] : angle = 180 # deplacement à gauche turtle.setheading(angle) turtle.forward(depl) start = c fonction principale pour affichage de l’animation turtle def afficheTurtle(tab,L): larg = len(tab[0]) haut = len(tab) fenX = 600 fenY = fenX*haut/larg scaleX = (fenX-20)/larg scaleY = (fenY-20)/haut turtle.setup(fenX, fenY) #Largeur : 600px, Hauteur : 400px turtle.bgcolor((0.9, 0.9, 0.9)) turtle.hideturtle() turtle.penup() turtle.setpos(-fenX/2+10,-fenY/2+10) turtle.setheading(90) turtle.pendown() #turtle.speed(0) turtle.tracer(False) # tracer le Laby avant de demarrer l’animation avec la tortue turtle.pensize(2) turtle.forward(fenY-20) turtle.left(-90) turtle.forward(fenX-20) turtle.left(-90) turtle.forward(fenY-20) turtle.left(-90) turtle.forward(fenX-20) turtle.left(-90) turtleLab(tab) turtle.tracer(True) # fin du tracé du Laby turtle.speed(6) turtlePath(tab,L) # animation du parcours par la tortue #calling for the mainloop() turtle.mainloop() Programme tab=labyrinthe(5,6) L = parcours((len(tab)-1,0),(0,len(tab[0])-1),tab) afficheTurtle(tab,L)
Principe Un modèle prédictif ne peut être établi qu’à partir d’une étude prealable de données. Une étude statistique permet de repérer si certains paramètres sont liés entre eux. Alors, si ces données étaient suffisamment nombreuses et précises, il est possible d’établir des lois mathematiques sur ces données. Une manière de représenter ce lien entre paramètres est d’établir une loi de regression linéaire, par exemple.
Utilisation du module unittest avec le calcul des nombres premiers avant de démarrer cette partie, il est recommandé de consulter :
le cours sur les tests unitaires Et le paragraphe sur mettre son programme sous forme de modules Définition: Un test unitaire est un test réalisé sur une portion du programme, typiquement sur une fonction.
Le module unittest offre des outils de test de code, comme la classe TestCase. Le but est des vérifier que votre code génère des résultats corrects, conformes au attentes.
Chiffrements symétriques Vocabulaire Chiffrer: transformer les caractères d’un texte pour le rendre incompréhensible, sauf pour celui qui possède la clé de chiffrement. Déchiffrer: transformer le texte chiffré en texte clair à l’aide de la clé de chiffrement Décrypter: transformer le texte chiffré en texte clair sans posséder la clé. Cryptologie: science du secret: possède deux branches cryptographie: étude de l’art du chiffrement cryptanalyse: analyse des méthodes de chiffrement pour les casser (décrypter) à quoi sert le chiffrement? Le chiffrement a pour but de protéger nos données, nos communications, mais aussi de signer nos messages et de s’assurer que l’on communique bien avec la bonne personne:
Sous-sections de Posts
jeu Space Invader
Ce mini projet sera l’occasion de mettre en oeuvre les notions vues dans le cours précédent sur :
la définition d’un objet en javascript
la gestion des évènements
l’utilisation d’une fonction callback avec un timer
Vous pourrez également suivre ce tutoriel avec la video à l’adresse :
lien video
Pour les images, on pourra faire un clic droit sur les liens proposés et choisir de télécharger le fichier.
Code minimal HTML
Le code html minimal qui permet de positionner un vaisseau aux coordonnées : 200px horizontal et 100px vertical :
<html>
<head>
<title>My space invader</title>
<script src="jeu.js"></script>
<style>
html,body {margin : 0px; padding: 0px; width : 100%; height: 100%}
body {background: url('fond.jpg'); background-size: cover; overflow: hidden;}
</style>
</head>
<body>
<img id="ship" src="ship.png">
<script type="text/javascript">
let v = document.getElementById('ship');
v.style.width = '100px';
v.style.height = 'auto'; // pour conserver le ratio
v.style.position = "absolute";
// regles de positionnement
// demarrer par la regle de positionnement absolute pour que
// l'image soit mise par rapport à l'élément precedent dans le flux
// de maniere absolute
v.style.left= '200px';
v.style.top='100px';
</script>
</body>
</html>
position du vaisseau à 200px à gauche et 100 px en bas
Le problème est que l’on ne veut pas avoir à taper tout ces volumes de code pour positionner un vaisseau un missile ou un alien : on va alors utiliser une librairie que l’on va nous même écrire.
On pourra effacer toutes les lignes écrites entre les balises <body> et </body>
le constructeur de Sprites : function Sprite( )
les propriétés liées aux attributs
Nous allors programmer une librairie javascript qui va nous permettre de concevoir un constructeur pour tous les objets à afficher. Chacun des ces objets aura alors des propriétés de positionnement, et deux options d’affichage : visible ou caché.
Commençons par programmer le constructeur et les attributs dont héritera l’objet. Dans le fichier jeu.js, mettre les lignes de code :
La function Sprite(filename, left,top){ : C’est une fonction de creation d’objets (contient des this et commence par majuscule)
Sprite : l’element à créer
this : l’objet lui meme et _node , c’est l’élément correspondant, avec tous ses attributs, tel qu’on l’avait défini de maniere statique dans le premier document html.
On peut déjà positionner l’objet à l’écran en écrivant dans la partie <script> de la page html : (ce sera alors la première ligne mise entre les balises <script> et </script>
let vaisseau = Sprite('ship.png',400,500);
Ce qui devrait construire un objet vaisseau, et ajouter un nouvel élément sur la page : l’image du vaisseau à la position 400px,500px.
Les propriétés de (re)positionnement
<input type="checkbox" id="toggle" class="visually-hidden">
<div class="control-me">
<p>On souhaite maintenant ajouter des méthodes particulières à l'objet, qui permettront de le déplacer facilement (le <span class="ital">repositionner</span>).</p>
<p>On pourrait le réaliser à l'aide d'une affectation simple, comme on l'a déjà vu dans le cours précédent. Par exemple, avec :
<code>Sprite.posX</code></p>
<p>Ici, on va utiliser la méthode Object.defineProperty(), qui permet de préciser le comportement attendu, potentiellement différent de celui par défaut.</p>
<p>On veut maintenant que la nouvelle propriété <code>left</code> soit accessible en ecriture ET en lecture de la manière suivante :
<ul>
<li>Ecriture : Avec le signe <code>=</code> d'affectation => <code>vaisseau.left = 400;</code> </li>
<li>Lecture : Sans le signe <code>=</code> pour accéder à la valeur => <code>vaisseau.left</code> </li>
</ul>
</p>
</div>
Une fois cette nouvelle méthode attachée au constructeur Sprite, on peut le représenter avec le schéma suivant :
classe Sprite
L’objet que l’on définira à partir de cette classe héritera des propriétés et des méthodes, que l’on appelera avec l’instruction objet.propriété ou objet.methode
Pour ajouter les méthodes : Dans le fichier jeu.js, enlever l’accolade finale du constructeur et mettre :
Object.defineProperty permet de definir une propriété pour l’objet que l’on a créé : on passe l’objet avec l’argument this
une propriété est un ensemble de 2 methodes :
une methode get d’acces en lecture.
une methode set d’acces en ecriture
Remarquer que l’on utilise _leftpour le nommage d’une prorieté qui reste privée (locale) dans ce constructeur.
Cette methode, on va y acceder avec le nom de proprietéleft:
On fait par exemple dans le script de la page principale : (ligne à écrire à la suite des autres instruction, avant la fermeture </script> dans la page html)
vaisseau.left = 400;
Le signe = va indiquer que l’on invoque la propriété leften ecriture (on dit que l’on invoque le setter), et cela va modifier l’attribut css style avec la nouvelle règle left : 400px`.
Rafraichissons la page.
Dans la console : explorons les attributs de l’élément associé à l’objet vaisseau :
On peut alors vérifier les valeurs prises pour les propriétés CSS des attributs.
Le reste du script sera mis entre les balises <script>de la page html.
On peut avoir accès à la dimension de l’écran avec un propriété de l’objet :
document : document.body.clientWidth
Centrer le vaisseau, au mileu de l’écran, en position basse avec l’instruction : remplacer let vaisseau = Sprite('ship.png',400,500); par :
let vaisseau = new Sprite("ship.png", document.body.clientWidth/2, 500);
A vous de jouer : ajouter 3 aliens que vous devrez repartir sur la largeur de l’écran, en position haute. Nommez les : alien1, alien 2, alien3.
Et ajoutez le missile, à une position quelconque, mais modifiez immédiatement sa propriété displaypour qu’il reste caché :
ajouter :
missile.display="none";
à gauche : missile visible, à droite : missile caché
Gestionnaires d’évènements
On ajoute un gestionnaire d’evenements lié aux touches appuyées avec :
document.onkeydown = function (event) {
lorsque l’on appuie sur une touche, cela genere un evenement "event" et appelle une fonction avec le parametre l’un des attributs possibles de event qui est keyCode : comme ici, l’evenement est lié aux touches appuyées, on peut demander le keyCode de ces touches :
Mettre les lignes suivantes dans le programme de la page html :
document.onkeydown = function (event) {
console.log(event.keyCode);
}
Cliquer alors dans la fenêtre du navigateur pour lui donner le focus, puis tester en appuyant sur diverses touches du clavier la valeur affichée dans la console :
f : 70
flèche droite : 39
flèche gauche : 37
s : 83
space : 32
Pour faire avancer le vaisseau à droite lorsque l’on appuie sur la touche f ou la flèche droite, il faut alors mettre :
document.onkeydown = function (event) {
if (event.keyCode==70 || event.keyCode==39 ){
vaisseau.left+=10;
}
A vous de jouer :
ajouter alors, dans le même bloc de code lié à la gestion d’evenements du clavier, les instructions consitionnelles qui feront :
avancer le vaisseau à gauche pour s ou pour flèche gauche
faire apparaitre le missile juste devant le vaisseau lorsque l’on appuie sur la barre espace.
limiter le déplacement à gauche et à droite pour ne pas que le vaisseau sorte de l’écran.
Animer les éléments
On va modifier à intervalle de temps réguliers les aliens et le missile, ce qui donnera l’illusion d’une trajectoire.
méthode setInterval()
Les méthodes setTimeout et setInterval sont des méthodes de l’objet Window.
Ce sont des processus indépendants qui, quand ils sont lancés par une instruction, ne bloquent pas l’affichage du reste de la page ni les actions de l’utilisateur.
Elles permettent de placer dans la pile des prochaines fonctions à exécuter une fonction particulière. Javascript exécute cette pile fonction après fonction dans l’ordre de la pile.
SetTimeout indique un délai avant exécution
setInterval déclenche une opération à intervalles réguliers
ClearTimeout interrompt le décompte de setTimeout et de setInterval
Syntaxe :
var intervalID = scope.setInterval(func ou bloc de code, [delay (en ms)]);
Ce compteur de temps est identifié de manière unique : window.setInterval renvoie une valeur numérique qui permet cette identification.
Dans le fichier jeu.js, en dehors du constructeur Sprite( ) (à la suite), ajouter :
Sprite.prototype.startAnimation=function(fct,interval){if(this._clock)window.clearInterval(this._clock);//s'il y a deja un missile qui est envoyé, clearInterval//retireletimerquiluiétaitliéetenmetunnouveauvar_this=this;//ondemarreunintervallequel'on associe à l'objetthis//ondéclareunenouvellevariablelocaleavecl'underscore _this//dontlaportéeseradescendante.Cettevariablepourraêtreutilisée//parlafonctionexecutéeparsetIntervalthis._clock=window.setInterval(function(){fct(_this);},interval);};Sprite.prototype.stopAnimation=function(){window.clearInterval(this._clock);};
Lorsque la touche barre espace est appuyée : on appelle la méthode startAnimation pour l’objet missile. Cette méthode appelle la fonction setInterval qui va associer un timer à l’objet lorsque l’on fait nom_de_l_objet.startAnimation(fct,interval). L’un des paramètres de la fonction setIntervalest justement une fonction, fct. On met moveMissile comme fonction de callback.
Le timer associé à l’objet, appelle à intervalle de temps régulier cette fonction qui est passée en paramètre (ce que l’on appelle un callback). L’intervalle de temps est donné par la paramètre interval. Ce qui modifie la pile d’appel des fonctions dans le programme.
fonction callback et pile d'appel des fonctions
La deuxieme propriété, stopAnimation, permet de retirer le timer avec l’instruction clearInterval().
Remarques : voir en annexe en bas du document
animation du missile
On va alors ajouter la fonction moveMissile(missile) qui sera appelée par setInterval :
Dans la partie <script> du programme de la page html : en dehors de la fonction anonyme executée par onkeydown, on ajoute :
function moveMissile(missile){
missile.top -=10;
if (missile.top<100) {
missile.stopAnimation(); // sortie de l'écran : on retire le timer de l'objet
missile.display = "none";
}
}
Lorsque la fonction est appelée, cela modifie la position du missile (on soustrait 10 px à sa position par rapport au haut de la page)
dans le bloc de code associé à la condition sur l’évenement de la touche appuyée (la n°32), ajouter : missile.startAnimation(moveMissile,20);
Le bloc de code doit maintenant avoir le contenu suivant :
if (event.keyCode == 32){
if (missile.display=="none"){
// condition qui permet de ne lancer un missile que
// si aucun missile n'est deja en vol
missile.display="block";
missile.left = vaisseau.left+vaisseau._node.width/2;
missile.top = vaisseau.top;
missile.startAnimation(moveMissile,20);
}
}
animation des aliens
On créé ensuite l’animation des aliens, avec un déplacement à droite puis à gauche, à l’aide de 2 nouvelles fonctions :
function moveAlienToRight(alien){
alien.left += 10;
if (alien.left > document.body.clientWidth-vaisseau._node.width){
alien.stopAnimation();
alien.top += 50;
alien.startAnimation(moveAlienToLeft,40);
}
}
function moveAlienToLeft(alien){
alien.left -= 10;
if (alien.left < 0){
alien.stopAnimation();
alien.top += 50;
alien.startAnimation(moveAlienToRight,40);
}
}
alien1.startAnimation(moveAlienToRight,40);
Puis on lance l’animation pour chacun des autres aliens :
alien2.startAnimation(moveAlienToRight,40); par exemple pour le 2e alien.
Enfin, on va programmer une méthode de verification de collision de sprite, mais au niveau de la librairie de sprites.
Ajout d’une méthode checkCollision
Dans le fichier jeu.js, ajouter les lignes de code suivantes pour vérifier si deux sprites se chevauchent
Si on veut savoir si le sprite missile chevauche le sprite alien1, on fait, dans la fonction de déplacement du missile :
missile.checkCollision(alien1)
La fonction retourne alors true si les 2 sprites se chevauchent.
L’appel de cette méthode de missile se fera dans la fonction moveMissile(missile). Ajouter les lignes suivantes :
if (alien1.display != "none" && missile.checkCollision(alien1)){
// on ne fait un test QUE si l'alien est visible
// sinon le missile traverse l'écran
missile.display="none";
missile.stopAnimation();
alien1.display="none";
alien1.stopAnimation();
// on retire l'alien
}
Prolongement
Il reste maintenant à programmer les conditions de collision du missile avec les autres aliens, et aussi la condition de collision des aliens avec le vaisseau, ce qui amènerait un Game Over.
Enfin, pour aller plus loin, on pourrait imaginer d’ajouter encore plus d’aliens, comme expliqué dans la vidéo (lien en début de document), de gérer un Score, et de pouvoir recommencer la partie.
Annexe
Pour comprendre en détail la manière avec laquelle on a programmé ce timer, il faudra revoir, dans le cours précédent ce que sont : une fonction callback, une fonction lambda, un objet et son prototype
Remarque à propos de la portée des variables : Le problème du this
Le code executé par setInterval() se fait dans un contexte séparé de celui de la fonction qui l’appelle. Conséquence : le mot clé thisne pointe pas vers l’objet local , mais il est associé au contexte global, window.
En dehors de tout contexte, pour un navigateur, this est l’objet window.
C’est la raison pour laquelle on choisit ici de déclarer :
var _this = this; juste avant la fonction anonyme qui fait appel à _this
Programme complet
page html
<html>
<head>
<title>My space invader</title>
<script src="jeu.js"></script>
<style>
html,body {margin : 0px; padding: 0px; width : 100%; height: 100%}
body {background: url('fond.jpg'); background-size: cover; overflow: hidden;}
</style>
</head>
<body>
<script type="text/javascript">
let vaisseau = new Sprite("ship.png",400,500);
let alien1 = new Sprite("ufo.png",100,100);
let alien2 = new Sprite("ufo.png",400,100);
let alien3 = new Sprite("ufo.png",700,100);
let missile = new Sprite("missile.png",100,100);
missile.display="none";
document.onkeydown = function (event) {
console.log(event.keyCode);
// l'un des attributs possibles de event est keyCode :
// comme ici, l'evenement est lié aux touches appuyées
// on peut demander le keyCode de ces touches.
// f : 70
// s : 83
// space : 32
if (event.keyCode==70 || event.keyCode==39 ){
vaisseau.left+=10;
}
if (event.keyCode==83 || event.keyCode==37 ){
vaisseau.left-=10;
}
if (vaisseau.left<=0) vaisseau.left = 0;
if (vaisseau.left >= document.body.clientWidth-vaisseau._node.width) vaisseau.left=document.body.clientWidth-vaisseau._node.width;
if (event.keyCode == 32){
if (missile.display=="none"){
// condition qui permet de ne lancer un missile que
// si aucun missile n'est deja en vol
missile.display="block";
missile.left = vaisseau.left+vaisseau._node.width/2;
missile.top = vaisseau.top;
missile.startAnimation(moveMissile,20);
// on appelle la methode startAnimation
// associée à l'objet missile
// avec la fonction missile comme premier parametre (callback)
// et 20 ms comme seconde parametre (mis dans interval
// par la fonction anonyme executée lorsque l'on appelle
// la methode)
}
}
}
function moveMissile(missile){
missile.top -=10;
if (missile.top<100) {
missile.stopAnimation(); // sortie de l'écran : on retire le timer de l'objet
missile.display = "none";
}
if (alien1.display != "none" && missile.checkCollision(alien1)){
// on ne fait un test QUE si l'alien est visible
// sinon le missile traverse l'écran
missile.display="none";
missile.stopAnimation();
alien1.display="none";
alien1.stopAnimation();
// on retire l'alien
}
}
function moveAlienToRight(alien){
alien.left += 10;
if (alien.left > document.body.clientWidth-vaisseau._node.width){
alien.stopAnimation();
alien.top += 50;
alien.startAnimation(moveAlienToLeft,40);
}
}
function moveAlienToLeft(alien){
alien.left -= 10;
if (alien.left < 0){
alien.stopAnimation();
alien.top += 50;
alien.startAnimation(moveAlienToRight,40);
}
}
alien1.startAnimation(moveAlienToRight,40);
alien2.startAnimation(moveAlienToRight,40);
alien3.startAnimation(moveAlienToRight,40);
</script>
</body>
</html>
fichier jeu.js
functionSprite(filename,left,top){this._node=document.createElement("img");this._node.src=filename;this._node.style.position="absolute";this._node.style.height="100px";this._node.style.width="auto";//this._node.style.left=left;//this._node.style.top=top;document.body.appendChild(this._node);Object.defineProperty(this,"left",{get:function(){returnthis._left;},set:function(value){this._left=value;this._node.style.left=this._left+"px";}});Object.defineProperty(this,"top",{get:function(){returnthis._top;},set:function(value){this._top=value;this._node.style.top=this._top+"px";}});Object.defineProperty(this,"display",{get:function(){returnthis._node.style.display;},set:function(value){this._top=value;this._node.style.display=value;}});this.left=left;this.top=top;}Sprite.prototype.startAnimation=function(fct,interval){if(this._clock)window.clearInterval(this._clock);//s'il y a deja un missile qui est envoyé, clearInterval//retireletimerquiluiétaitliéetenmetunnouveauvar_this=this;//ondemarreunintervallequel'on associe à l'objetthis//ondéclareunenouvellevariablelocaleavecl'underscore _this//dontlaportéeseradescendante.Cettevariablepourraêtreutilisée//parlafonctiondéclaréethis._clock=window.setInterval(function(){fct(_this);},interval);};Sprite.prototype.stopAnimation=function(){window.clearInterval(this._clock);};Sprite.prototype.checkCollision=function(other){return((this.top+this._node.height>other.top)&&(this.top<(other.top+other._node.height))&&(this.left+this._node.width>other.left)&&(this.left<other.left+other._node.width))}
le DOM ou Document Object Model, une interface qui fait partie du BOM (Browser Object Model) et grâce à laquelle nous allons pouvoir manipuler le contenu HTML et les styles de nos pages.
Le DOM est ainsi une représentation structurée du document sous forme « d’arbre » crée automatiquement par le navigateur, à partir de sa lecture du document HTML.
Chaque branche de cet arbre se termine par ce qu’on appelle un nœud, contenant les éléments HTML. On va finalement pouvoir utiliser ces objets, leurs propriétés et leurs méthodes en JavaScript.
Le DOM fournit le squelette du document
Inspecter le DOM se fait avec le navigateur
inspecter le DOM dans le navigateur
C’est en particulier l’interface Document que nous allons utiliser pour parcourir le DOM : Toute opération sur le DOM commence avec l’objet document :
arbre du DOM
Trois noeuds du DOM sont disponibles directement comme des propriétés de l’objet DOM :
document.documentElement
document.body
document.head
On verra plus loin les méthodes de parcours de l’arbre du DOM (## parcourir l’arbre du DOM).
Manipuler les éléments de la page
accéder à un élément à l’aide d’un sélecteur
Pour manipuler les éléments d’une page affichée dans le navigateur, on doit accéder à cet élément.
Or, il n’y a pas de lien direct entre html et javascript :
En Javascript, on peut récupérer une instance de HTMLElement correspondant à un élément de la page.
Cela peut se faire à l’aide des ancres laissées sur ces éléments. On peut les sélectionner, comme en CSS avec leur classe, leur ID ou le nom de la balise. Pour réaliser ceci, on utilise les fonctions suivantes:
document.getElementById() permet de sélectionner un élément html à partir de son id.
document.querySelector() un sélecteur plus générique qui sélectionne les éléments à la manière des sélecteurs css.
Un premier exemple : afficher du texte
lorsque l’on souhaite injecter du texte dans un paragraphe dont l’attribut id="ancre", un élément que l’on aura défini dans la partie html du code avec :
<p id = "ancre"></p>
on utilisera dans la partie javascript:
document.getElementById('ancre').innerHTML = "nouveau texte à afficher".
Exemple 2 : modifier l’attribut style de l’élément
soit un élement avec attribut id=‘elem’ de la page :
On cherche à atteindre cet élément et en modifier la couleur :
(écrire le code suivant dans un fichier que vous nommerez exemple1.html)
<body>
<h1 id="elem">Un titre qui n'a pas de couleur</h1>
<script>
let elem = document.getElementById('elem');
elem.style.background = 'red';
</script>
</body>
On met cet élément dans une variable elem. Puis on peut modifier ses attributs, comme par exemple celui style pour la couleur.
Ouvrir le fichier avec un navigateur. La couleur du titre devrait apparaitre … en rouge !
Exemple 3 : utilisation de querySelector
Cette méthode associée à document permet d’utiliser les mêmes règles de selection que lorsque l’on utilise le CSS. On peut donc utiliser comme paramètre : le nom de la balise ‘p’, la classe de l’élément ‘.maclasse’, l’identifiant ‘#elem’, …
La propriété childNodes de l’interface Node renvoie une liste sous forme de tableau des nœuds enfants de l’élément donné. Le premier nœud enfant reçoit l’indice 0 comme pour tout tableau.
Et pour obtenir l’élément parent d’un noeud, on utilise la propriété parentElement.
Exemple :
Vous pouvez tester cet exemple en enregistrant le code suivant dans un fichier que vous nommerez exemple3.html:
<body><div><pid="myP">Un peu de texte, <a>un lien</a> et <strong>une portion en emphase</strong></p></div></body>
Ouvrir alors la page pour l’afficher dans le navigateur.
Cette page a alors l’arbre de DOM suivant qui lui est associé :
arbre du DOM
Le premier enfant de <p> est un nœud textuel, alors que le dernier enfant est un élément <strong>. Cet élément <strong> possède pour noeud enfant un noeud textuel dont le contenu et une portion en emphase
Dans la console, saisir une à une les instructions suivantes : (sans les commentaires)
>letparagraph=document.getElementById('myP');// pour stocker le noeud parent.
>letfirst=paragraph.firstChild;// parcours de l'arbre jusqu'au 1er enfant
>alert(first.nodeValue);// pour récuperer le contenu du noeud textuel
contenu textuel du premier enfant
Puis :
>letlast=paragraph.lastChild;>alert(last.firstChild.data);// pour recuperer le contenu textuel de la balise
contenu textuel du dernier enfant
On peut réaliser cette dernière manipulation en ayant recours à la liste de tous les enfants de paragraph: en écrivant dans la console :
> paragraph.childNodes
liste de tous les enfants du noeud parent
On peut lire dans la console que le noeud textuel (<strong>Une portion avec emphase</strong>) est au rang 3 dans la liste des noeuds enfants (childNodes).
On affiche alors son contenu textuel : dans la console, écrire :
Pour finir, on peut modifier à volonté les éléments textuels en modifiant la valeur renvoyée par .data ou .nodeValue :
Dans la console :
>last.firstChild.data='un autre texte'
modification du contenu textuel de last
Ajouter un paragraphe dans la page
Pour créer un nouvel élément dans la page :
créer un nouveau noeud an appelant la fonction creatElement associée à document
ajouter la balise textuelle associée à ce noeud s’il y en a une
ajouter eventuellement des attributs à cet élément: setAttribute(attribut,valeur)
ajouter cet élement directement à son noeud parent: appenChild
Exemple :
<head><metacharset="utf-8"/><script>varx=10;/*Affichelavaleurdelavariablex.Puisincrémentede1lavaleurdelavariablex*/functionaddXToThePage(){letnewP=document.createElement('p');newP.innerHTML="<p>La valeur de x = "+x+"</p>";newP.setAttribute('style','color : red;');document.getElementById("newPar").appendChild(newP);x=x+1;}</script></head><body><buttononclick="addXToThePage();">Cliqueicipourafficherlavaleurdelavariablex</button><divid="newPar"></div></body>
Résultat : (cliquer sur le bouton pour tester le programme)
Lire et modifier un tableau
Le programme suivant montre l’utilisation d’un formulaire. Lors du clic sur le bouton, on accède aux valeurs des champs du formulaire avec la propriété .value associée à l’élément du formulaire.
On recopie alors chacune des colonnes du tableau avec ces valeurs.
Pour accéder à chaque élément de la page, on utilise les règles de selection vues plus haut, avec document.getElementById et document.querySelector.
L’exemple présenté ici est incomplet et ne renvoie dans le tableau que le champ prenom. Il faudra completer le script pour renvoyer aussi les noms et email.
concevoir une page avec tableau en 100% javascript
Dans l’exemple suivant, on va voir la création d’un tableau d’une seule rangée, mais avec de nombreuses cellules. On va donc utiliser une boucle bornée, pour sa création, mais aussi pour relever les valeurs.
Une table en HTML est réalisée à partir d’éléments qui ont la hierarchie suivante :
L’élément form est parent d’un élément table, lui même parent de tbody, parent de tr (le ou les rangs) qui possède, lui plusieurs enfant td, un par cellule :
arbre du DOM pour le tableau
On commence par selectionner le noeud de l’élément form :
letform=document.getElementsByTagName("form")[0];
Au début du script on créé les différents noeuds pour ces éléments. Par exemple :
lettbl=document.createElement("table");
On créé un noeud pour l’élément input qui sera mis dans chaque cellule. Ce noeud est affecté à la variable cellText.
On créé les attributs de cet élément. On utilise la méthode setAttribute(attribut,valeur) :
cellText.setAttribute("type","text");
On ajoute alors le noeud au DOM avec :
document.body.appendChild(cellText);
L’élément créé est alors : <input type="text">
Pour chaque cellule td du tableau, on ajoute l’élément input :
cell.appendChild(cellText);
Puis on ajoute l’élément td au noeud tr :
row.appendChild(cell);
Puis l’élément tr à tbody, lui même à table, et table à form.
Choisir le dossier TP4_data_analyse puis le notebook algoKNN.ipynb.
Exercez vous en suivant le tutoriel avec ce notebook.
Principe
On cherche une correspondance entre les caractéristiques physiques d’un joueur de basket et son poste sur le terrain.
Pour simplifier, on considerera que les postes sont au nombre de trois :
le joueur Centre, noté ‘C’ (position 5 sur le schéma)
Le joueur Ailier, noté ‘F’ (positions 3 et 4 sur le schéma)
Le joueur arrière ou meneur de jeu, noté ‘G’ (positions 1 et 2 sur le schéma)
image URI
Il nous faut, pour rechercher une correspondance, avoir accès à une base de données des joueurs de basket, jouant par exemple dans un même championnat.
En étudiant cette première population, on va pouvoir prédire quel poste pourrait occuper un nouveau joueur entrant dans ce championnat (qui serait drafté), à partir de ses seules caracteristiques physiques.
Cette idée est un peu simpliste : le poste occupé sur le parquet ne dépend pas, bien sur des seules caractéristiques physiques, mais aussi des copétences du joueur.
Mais nous allons chercher dans ce TP si l’idée est plutôt cohérente.
On traite alors un jeu de données bi-dimentionnelles à N classes (où N estle nombre de postes occupés par les joueurs).
On va pour cela utiliser l’algorithme des k-plus-proches-voisins. C’est l’un des algorithmes les plus utilisés dans le domaine de l’apprentissage automatique ou machine learning.
Comme pour tous les types d’apprentissage automatique, le principe est le suivant :
on commence par étudier une population donnée, dite d’entrainement. La qualité d’échantillonnage utilisé pour cette population va déterminer la bonne prédiction par cet algorithme. L’étude de cette population doit permettre de créer des ensembles d’objets aux propriétés similaires. Par exemple, l’ensemble constitué des joueurs de type Centre seront probablement plus grands et plus forts que les autres joueurs.
On dispose ensuite d’une population exterieure à cet échantillonnage. On cherche à prevoir leur position sur le terrain par rapport à leurs caractéristiques physiques, d’après les résultats de l’étude préalable.
La ligue de basket americaine contient environ 400 joueurs professionnels. La plupart de nationalité américaine. On dispose d’un extrait de ce fichier (voir dans le dossier datas), constitué de 57 joueurs, classés par ordre alphabetique.
Chargement du fichier base de données
Python : librairies numpy et pandas
Le traitement des données se fera en langage Python.
On commence par charger les librairies utiles pour le traitement de ces données. Puis on transforme celles-ci en un DataFrame, une sorte de tableau à 2 entrées. Les valeurs de taille et de poids sont toutes de type float après ce premier traitement.
tableau_reduit.head()# on affiche le debut du tableau avec la fonction .head()
Filtrer les données du DataFrame
On peut maintenant filtrer les joueurs du tableau selon le poste du joueur.
On utilise pour cela la fonction .loc associée au DataFrame. On met en paramètre un predicat qui sera testé pour chacun des objets du DataFrame. Seuls les objets au prédicat true sont conservés :
Question : Dans cet exemple : A quel poste jouent les joueurs conservés dans le DataFrame ensemble? Vérifiez le dans la console…
Afficher les joueurs sur un graphique taille-poids
On créé une fonction points qui ajoute le nuage de points pour chacun des éléments de la liste postes mise en paramètre. On créé un nuage de points de couleur et d’étiquette différent pour chaque poste occupé.
Les paramètres de cette fonction :
postes : on peut y mettre le caractère correspondant au poste comme ‘G’, ‘F’, ou ‘C’. On peut aussi y mettre une liste constituée de certains, ou tous les postes.
Les autres paramètres sont optionnels : il s’agit de la taille et de la forme du marqueur, et de la transparence.
importmatplotlib.pyplotaspltfrommatplotlib.patchesimportEllipse,Circledefpoints(postes,size=20,marker='o',alpha=0.5):"""
fonction qui ajoute des points au graphique existant
Le paramètres :
* postes peut être une liste de postes comme par exemple ['G','F','C']
ou bien un seul poste, comme par exemple 'C'
* les autres paramètres sont optionnels
"""forposteinpostes:ensemble=tableau_reduit.loc[tableau_reduit['poste']==poste]x=ensemble['taille']y=ensemble['poids']plt.scatter(x,y,label=poste,s=size,marker=marker,alpha=alpha)
Avec les lignes suivantes, on affiche sur un même graphique les joueurs du tableau jouant aux postes ‘G’, ‘F’, ‘C’.
Les joueurs du poste ‘C’ sont mis en relief avec un marqueur plus gros.
Question : Repérez à quel endroit se regroupent les joueurs ‘C’…
plt.title('caractéristiques des joueurs de NBA 2020')plt.xlabel("taille")plt.ylabel("poids")plt.grid(which='major',linestyle='-',linewidth='0.5',color='red')points(['F','G'])points('C',100,'D',1)axes=plt.gca()plt.legend()plt.savefig('datas/centre.png')plt.show()
Travail : Utilisez la fonction points pour représenter les 3 ensembles ‘C’, ‘F’ et ‘G’. Mais cette fois, on veut mettre en relief :
les joueurs ‘F’ dans un 2e graphique
Puis mettre en relief les joueurs ‘G’ dans un 3e graphique.
# Correctionplt.title('caractéristiques des joueurs de NBA 2020')plt.xlabel("taille")plt.ylabel("poids")plt.grid(which='major',linestyle='-',linewidth='0.5',color='red')points(['G','C'])points('F',100,'D',1)axes=plt.gca()plt.legend()plt.savefig('datas/ailier.png')plt.show()
# Correctionplt.title('caractéristiques des joueurs de NBA 2020')plt.xlabel("taille")plt.ylabel("poids")plt.grid(which='major',linestyle='-',linewidth='0.5',color='red')points(['F','C'])points('G',100,'D',0.5)axes=plt.gca()plt.legend()plt.savefig('datas/arriere.png')plt.show()
Prediction du poste du joueur
population dont le poste est inconnu
Certains joueurs ont des caractéristiques qui les rendent plus polyvalents.
Question : En observant le tableau_reduit en entier : Quels sont ces postes polyvalents ?
Ces joueurs n’ont été mis sur aucun des graphiques d’apprentissage vus plus haut. Et si vous utilisiez un algorithme prédictif pour deviner le meilleur poste auquel ils devraient être ?
Nous allons étudier en détail cet algorithme, des k plus proches voisins…
Prenons par exemple les joueurs polyvalents à l’étiquette “G-F”. Ces joueurs, sont-ils plutôt pressentis pour être G (arrière), ou F (ailier) ?
C’est ce que nous allons chercher à déterminer.
Travail : en utilisant la méthode .loc associée au DataFrame tableau_reduit : filtrer les joueurs dont le poste est ‘G-F’, et affecter ce nouveau DataFrame à la variable ensemble
Afficher alors ce nouveau tableau
Travail : Repérer le numéro de l’index du premier joueur au poste ‘G-F’ dans ce tableau. Afficher l’ensemble des informations relatives à ce joueur à l’aide de l’instruction ensemble.loc[numero index]
# Correctionensemble.loc[9]
Utiliser la fonction joueur() pour l’afficher sur le graphique
Affichons un marqueur pour ce joueur au milieu de la distribution d’entrainement.
Pour cela, on utilise une fonction de nom joueur() dont les paramètres sont les suivants :
num : le numero de l’index du joueur dans le tableau
rayon : le rayon du cercle dans lequel on recherche les k-plus proches voisins. Ce rayon est mesuré dans une unité relative au poids du joueur. L’echelle de l’axe des abscisses, la taille étant très différente, on réalise un calcul prenant en compte le ration DX/DY pour exprimer l’éloignement dans cette direction (un ecart de 10kg n’a pas la même signification qu’un écart de 10cm…)
defjoueur(num,rayon):"""
positionne le point relatif au joueur de numero num
et trace un cercle de rayon r exprimé dans une unité relative à l'axe des Y
Le demi axe de l'ellipse pour X est calculé par rapport au ratio = DX/DY :
r_X = r_y*ratio
"""ratio=0.005# echelle des X / echelle des Yplt.title('caractéristiques des joueurs de NBA 2020')plt.xlabel("taille")plt.ylabel("poids")plt.grid(which='major',linestyle='-',linewidth='0.5',color='red')points(['F','G','C'])x=ensemble.loc[num]['taille']y=ensemble.loc[num]['poids']plt.scatter(x,y,label=poste,s=50,marker='P',alpha=1)circle=plt.Circle((x,y),1,color='r')fig=plt.gcf()# gcf() signifie obtenir le chiffre actuelax=fig.gca()# gca() signifie Obtenir l'axe actuelax.set_aspect(ratio)# je choisi le ratio DX/DY pour les echelles des axesax.add_artist(Ellipse((x,y),rayon*ratio,rayon,color='yellow',alpha=0.2))plt.legend()plt.savefig('datas/joueur'+str(num)+'.png')plt.show()
Afficher le joueur sur le graphique
Travail : utiliser la fonction joueur() pour afficher un marqueur pour ce joueur. On prendra un rayon égal à 20 pour le paramètre rayon.
# correctionjoueur(9,20)
L’algorithme des k-plus proches voisins
L’algorithme des k-plus proches voisins peut s’écrire en langage naturel :
trouver dans la collection d’entrainement les k plus proches voisins du joueur
Parmi ces proches voisins, trouver la classification majoritaire
Renvoyer la classification majoritaire
Travail : Commencez par fabriquer un DataFrame ensembleG contenant tous les joueurs au poste ‘G’.
Puis, avec cette même methode, construire les DataFrame ensembleF et ensembleC
Puis ajoutons une nouvelle colonne avec la distance au joueur de numero num dans le graphique :
defdistance(num,ratio):x=tableau_reduit.loc[num]['taille']y=tableau_reduit.loc[num]['poids']ensemble['dist']=ensemble.apply(lambdarow:(((row["taille"]-x)/ratio)**2+(row["poids"]-y)**2)**0.5,axis=1)# On trie le tableau par valeur dist croissanteensemble_trie=ensemble.sort_values(by='dist')returnensemble_trie
ensemble_trie=distance(9,0.005)
ensemble_trie
Trier les résultats
On voudrait maintenant dénombrer, par poste, les joueurs aux caractéristiques les plus proches de notre joueur au poste inconnu. Sur un echantillon des k premiers joueurs du tableau précédent.
Travail : Créer une fonction knn(k) qui renvoie un dictionnaire score avec pour chacune des clés, ‘G’, ‘F’, et ‘G’, le nombre de joueurs du tableau parmi les k premiers.
On peut afficher les 3 premiers joueurs du tableau trié, avec l’une des méthodes associée au DataFrame :
DataFrame.head(nombre de lignes à afficher)
ensemble_trie.head(3)
knn(3)
Travail : Ecrire une fonction qui renvoie le poste le plus représenté selon la valeur de k choisie. Faites alors quelques essais. Conclure quand à la pertinence du résultat selon la valeur de k choisie.
Prolongement
On peut réaliser ce même travail : pour rechercher les k plus proches voisins :
d’un autre joueur au profil ‘G-F’
pour un joueur d’un autre profil, comme par exemple ‘F-G’
L’intelligence artificielle désigne des algorithmes plus ou moins évolués qui traitent des problèmes dont la résolution fait appel à l’intelligence humaine. Ils imitent des actions humaines.
Le comportement de l’algorithme évolue au cours du temps, en fonction des données qui lui sont fournies.
Aujourd’hui, ce sont les chatbots qui illustrent le mieux cette notion d’IA. Il existe ainsi:
les chatbots basés sur des règles: (plus simples que l’ IA):
suivent un ensemble de règles pré définies
servent pour un flux de discussion prédeterminé
doivent être configurés à chaque mise à jour
les chatbots basés sur IA:
comprennent le contexte, interprètent l’intention d’une conversation
peuvent apprendre des interactions
peuvent traiter des projets plus complexes
Les chatbots issus de l’IA conversationnelle: sont des technologies grâce auxquelles les logiciels peuvent converser avec des personnes en utilisant le langage naturel.
Voir en particulier la video sur le machine learning et les reseaux de neurone, après 10min: Lien vers la video
Analyse de données et machine learning
une définition
imaginons que vous vouliez créer une IA qui vous donne le prix d’un appartement à partir de sa superficie.
Dans les années 1950, vous auriez fait un programme du type « si la superficie est inférieure à 20m², le prix vaut 60 000€, si elle est entre 20m² et 30m², le prix vaut 80 000€, etc… », ou peut-être « prix = superficie*3 000 ».
Mais ce type de problème ne peut pas être résolu de manière satisfaisante avec de telles approximations: il vaudrait mieux constater le prix de plusieurs appartements, issus de différents quartiers, de qualités différentes (des variables, comme la superficie, l’exposition, le vis-à-vis…). On pourra alors estimer le prix d’un nouvel appartement non-référencé selon ses caractéristiques (ses variables).
C’est ce type de démarche qui est attendu lorsque l’on fait du machine learning, ou de l’apprentissage autonome. C’est un sous-domaine de l’intelligence artificielle. En pratique, le programme va analyser une partie des données pour rechercher les corrélations ou les similitudes entre les objets. Il va alors former des classes, ou établir des relations, ou des probabilités.
Le machine learning est un domaine large, qui comprend de très nombreux algorithmes. Parmi les plus célèbres, on retrouve :
Les régressions (linéaires, multivariées, polynomiales, régularisées, logistiques…) : ce sont des courbes qui approximent les données
L’algorithme de Naïve Bayes : l’algorithme donne la probabilité de la prédiction, sachant les événements antérieurs. Par exemple, quel est le prix le plus probable sachant que l’appartement X fait 43.7m², qu’il occupe une position privilégiée dans le quartier Montmartre, en rez de jardin, sans parking, sans vis-à-vis… voir à ce sujet l’excellent article sur le blog sciencesetonnantes de David Louapre : probabilités conditionnelles (Bayes)
Le clustering : toujours grâce aux mathématiques, on va grouper les données en paquets de manière à ce que dans chaque paquet les données soient les plus proches possibles les unes des autres. C’est utilisé notamment pour des recommandations (films, articles achetés…)
Les arbres de décision : en répondant à un certain nombre de questions et en suivant les branches de l’arbre qui portent ces réponses, on arrive à un résultat (avec un score de probabilité)
Ainsi que des algorithmes plus perfectionnés reposant sur plusieurs techniques de statistiques
Les domaines professionnels
Tous les champs professionnels, du moment où il y a des données qui sont collectées :
dans l’entreprise, le commerce, dans la recherche, …
Ces données sont collectés à partir d’objets connectés, à partir de l’activité des internautes sur les sites de e-commerce (marketing digital), des statistiques d’utilisation de produits, de véhicules, de bâtiments, voire des données collectées suite à des évènements naturels, biologiques, etc.
Ces données peuvent servir les domaines de la santé (suivi de la propagation d’épidémies, aide au diagnostic,… des transports (analyse de flux,), de l’environnement (prévisions météorologiques, contrôle de la pollution), mais aussi dans l’analyse de la clientèle dans l’industrie et le commerce.
En se basant sur des informations passées, les techniciens spécialisés dans l’observation des grosses données (big datas) peuvent ainsi faire des prévisions dans chacun de ces domaines. Ou prendre des décisions en fonction des variables.
Le principe : on récupère les données, on les nettoie, on les explore, puis on utilise nos algorithmes pour créer de l’intelligence (artificielle) qui aide à la prévision/décision. Ces algorithmes sont basés sur des outils statistiques. La machine qui execute un tel algorithme est capable d’apprendre de manière autonome, dans une séquence où les données collectées servent à établir un modèle. La machine améliore son modèle grâce à un score associé à l’exploitation des données. Puis elle utilise ce modèle lorsque le score est optimal pour résoudre une série de problèmes.
Exemples :
biologie :
Expressions de gènes (transcriptome, relation gène / protéines)
Paléontologie et évolutions
médecine : Pharmacovigilance
chimie :
Prédiction de la toxicité des molécules, mécanismes réactionnels
physique :
Astronomie : répertoire des corps célestes
Expériences en physique des particules (LHC au CERN)
sciences environnementales :
Comprendre les milieux naturels, l’impact de l’homme, etc
sciences sociales :
Analyse d’opinions sur le Web
Analyse des recherches sur le Web : Google Trends
Vocabulaire
dataset : jeu de données. Ce jeu de données peut en contenir un petit nombre ou un très grand nombre de données (big data). Ces données peuvent être discretes (qualitatives) ou continues (valeurs numériques).
big data : données massives. Des données qui sont collectées en continu et en grande quantité. Cela constitue un flux si important qu’il est obligatoire d’utiliser des techniques de traitement spécifiques au domaine du machine learning pour pouvoir les exploiter. On décrit le big data à l’aide des 3V : Volume, Velocity (peu de temps pour traiter les données), Variety (des données diverses)
Une classe : c’est un champ particulier à valeurs discrètes.
Différents type de programmes en analyse de données : programme de classification, de prédiction, d’estimation, d’association.
La classification : consiste à examiner les caractéristiques d’un objet et lui attribuer une classe :
attribuer ou non un prêt à un client
établir un diagnostice
placer une roche, une espèce végétale, animale… dans une catégorie
Prédiction : consiste à prédire la valeur future d’un attribut en fonction d’autres attributs. Deux exemples :
Regression : estimer le chiffre d’affaire d’un nouveau magasin, estimer le prix du loyer en fonction de la surface de l’habitation
classification supervisée : estimer la probabilité qu’un client pratique un sport donné à partir de l’historique de ses achats
Modèles prédictifs : utilisent les données avec des résultats connus pour développer des modèles permettant de prédire les valeurs d’autres données.
Modèle descriptif : propose des descriptions des données pour aider à la prise de décision. C’est un modèle surtout utilisé en segmentation et association.
Apprentissage supervisé : les données à analyser comprennent à la fois des données d’entrée et de sortie. On connait la classe des objets, et on cherche à prévoir l’appartenance à une de ces classes pour tout nouvel objet.
Lorsque l’on cherche à comprendre ou définir une relation entre les données, on peut pratiquer une association : qui consiste à déterminer les attributs qui sont corrélés :
C’est ce que l’on réalise lorsque l’on fait l’analyse d’un panier de courses au supermarché (ou sur un site d’e-commerce) : poisson et vin blanc sont deux articles qui vont souvent occuper ensembles le panier.
Apprentissage non supervisé : Seules les entrées sont fournies. Par exemple : identifier des familles de fournisseurs et de clients pour faire un mailing ciblé
Une technique pratiquée en apprentissage non supervisé : la Segmentation : consiste à former des groupes homogène à l’intérieur d’une population (des clusters).
Les étapes du traitement de données
Aggréger ces données dans un data lake.
Nettoyer les données. C’est à dire s’assurer qu’elles sont consistantes, sans valeurs aberrantes ni manquantes, et mises dans le bon format.
Explorez les données. Cette étape doit permettre de mieux comprendre les différents comportements et de bien saisir le phénomène sous-jacent. On cherche:
soit à réaliser une classification, par exemple sous forme arborescente. C’est ce que l’on cherche à réaliser lorsque l’on peut discriminer la population à trier à partir de critères qualitatifs. L’idée est alors de trouver les bonnes clés de tri, qui vont partager la population.
soit à chercher une corrélation entre grandeurs, si celle-ci sont numériques. Chaque donnée observée est l’expression d’une variable aléatoire générée par une distribution de probabilité. On cherche alors à énoncer une conclusion du type : “suite à l’exploration, il y a clairement une relation entre X et Y, ces 2 grandeurs semblent liées par une relation de regression linéaire (ou non linéaire) du type Y = a*X + b (ou autre)”.
Modéliser les données.
Dans le premier cas, à partir de valeurs dites discrètes (des catégories), on devra réaliser une segmentation des objets en entrée en différentes catégories. La prédiction réalisée à partir d’une nouvelle entrée donne en sortie une liste de labels possibles.
Dans le deuxième cas, il s’agira d’un traitement statistique des données.
illutration de la différence entre classification et regression linéaire
Déployer le modèle. Une fois le modèle établi, on va encore le vérifier et l’ajuster à partir de certaines des données : il faudra donc prévoir une séparation initiale de ces données : certaines des données servent à générer le modèle (le training set). Les autres sont celles qui vont permettre de valider (tester) ou améliorer si besoin le modèle (le testing set).
Prévoir la catégorie ou faire de la prédiction à partir des nouvelles données.
Le machine learning est l’apprentissage d’un modèle statistique par la machine grâce à des données d’entraînement. Un problème de machine learning comporte parmi les étapes une mesure des performances. S’il améliore les performances sur cette tâche lorsqu’on lui fournit les données d’entraînement, on dit alors qu’il apprend.
mots clés :Données discretes, règles d’association, apprentissage non supervisé.
La recommandation est une problématique qui revient très souvent dans l’ananlyse de données pour le marketing électronique. La recommandation se base sur des similarités entre utilisateurs, ou bien des similarités entre produits. Ce filtrage collaboratif repose sur l’adage : Si deux personnes ont aimé des contenus identiques par le passé, elles ont une probabilité élevée d’aimer les mêmes choses dans le futur.
Sur l’image ci-dessous, on regarde par exemple ce qu’ont voté les utilisateurs similaires, c’est-à-dire ceux qui ont déjà voté la même chose sur d’autres produits (surlignés en vert). On peut alors prédire ce qu’aurait voté notre utilisateur sur le produit cherché, et ne proposer que les produits sur lesquels il aurait mis un pouce vert.
Les utilisateurs similaires (en vert) n'ont pas aimé le produit que notre utilisateur n'a pas encore noté. L'algorithme aura donc tendance à prédire une mauvaise note et à ne pas recommander le produit ici
Les utilisateurs similaires (en vert) n’ont pas aimé le produit que notre utilisateur n’a pas encore noté. L’algorithme aura donc tendance à prédire une mauvaise note et à ne pas recommander le produit ici.
En pratique : On peut voir la liste des profils utilisateurs comme une matrice. L’objectif d’un algorithme de recommandation est de remplir les cases vides de cette matrice. Quel serait le score de Gregory (dernière ligne du tableau) pour l’article “ordinateur portable”, marqué avec un ?. Il faudra établir une correspondance entre les objets et les profils.
Il existe alors plusieurs méthodes d’association :
l’association basée sur les clients (voir exemple ci-dessus)
On pourrait par exemple, calculer un coefficient de similitude entre Gregory et les autres usagers pour tous les articles renseignés, puis établir une liste triée.
l’association basée sur les objets (l’exemple dit du panier de la ménagère)
une liste d'achats
Cette fois on ne s’interesse plus au profil du client, mais on cherche une règle d’occurence entre les objets. Pour trouver les associations entre 2 produits, on construit le tableau de co-occurrence montrant combien de fois 2 produits ont été achetés ensemble.
tableau de co-occurence
Ici : le produit A apparaît dans 80% des achats, le produit C n’apparaît jamais en même temps que le produit E, les produits A et D apparaissent simultanément dans 40% des achats.
Ces observations peuvent suggérer une règle de la forme : « Si un client achète le produit A ALORS il achète le produit D ».
On cherche alors à générer des règles du type : si A alors D avec, pour chacune, un pourcentage de confiance. Par exemple, cette règle apparaissant ici apparaissant dans 40% des achats, on considère que le pourcentage de confiance est égal à 40%.
Le clustering
mots clés :Données continues, apprentissage non supervisé, algorithme des k-plus proches voisins
Le clustering désigne les méthodes de regroupement automatique de données qui se ressemblent le plus en un ensemble de “nuages”, appelés clusters. On cherche repérer, et mesurer la similarité entre les différentes données. Par exemple, les points sur le graphe ci-dessous peuvent être considérés comme similaires s’ils sont proches en termes de distance.
L'objectif du clustering est de retrouver les différents clusters de données, c'est-à-dire de regrouper les données similaires entre elles
On pourra étudier cet exemple en détail avec la page Python algo KNN de ce même site.
utilisation d’un arbre de décision
mots clés :Données discretes ou continues, classes, attributs, segmentation.
A partir dʼun ensemble de valeurs d’attributs, il sʼagit de prédire la valeur d’un autre attribut (variable cible).
Un arbre est équivalent à un ensemble de règles de décision.
L’idée est de bien choisir l’(les) attribut(s) discriminant(s). L’arbre est construit en découpant successivement les données en fonction des variables prédictives. L’algorithme qui realise ce travail utilise des grandeurs statistiques pour mesurer la qualité de la segmentation.
Une fois l’arbre construit, pour prédire la classe (la variable cible) d’une nouvelle entrée (une instance), il faut parcourir l’arbre depuis la racine jusqu’à la feuille.
Exemple 1 : Il s’agit de prédire si, selon la météo(ciel, temp., humidité et vent), on va aller jouer au tennis.
construction d'un arbre de décision
Chaque chemin, depuis la racine jusqu’à une feuille est une règle de décision. Par exemple ici : si ('ciel' == 'soleil') et ('temp.' == 'doux') et ('humidité' = 'élevée') et ('vent' == 'faible' ) alors (classe = 'oui')
Exemple 2 : Arbres de classification et régression
On peut aussi réaliser ce type de segmentation avec des attributs à valeurs continues. On cherche alors à regrouper déterminer des clusters à partir du regroupement des classes.
L’exemple suivant montre la répartition des éléments dans un diagramme (x1;x2). Une fois ce premier travail réalisé, on pourra construire un arbre de classification à partir des tests sur x1 et x2. Par exemple
si x2<0.42 alors classe = 'Vert'
résultat obtenu par recherche de clusters sur un jeu de données bidimensionnelles à trois classes
Choisir alors le fichier : algorithme de recommandation.ipynb
Il s’agit d’un cas très classique d’algorithme utilisé dans le web marketing. Un client choisit et met dans ses favoris un article, ou dans son panier. Le site lui propose des articles compatibles, ou similaires. La recommandation peut être basée sur la description de ces articles. L’algorithme va alors chercher les articles qui ont le plus de points communs dans leur description; c’est à dire le plus de mots communs dans leur description.
La première étape pour calculer les similarités consiste à découper les descriptions en listes de mots (c’est la tokenisation) puis à prendre les racines des mots, les stems.
Extraire les mots d’un texte
Prenons un exemple avec le texte suivant :
texte="""
Mardi 20 février, à la médiathèque des Mureaux (Yvelines), le chef de l’Etat a accompagné
la locataire de la rue de Valois pour la remise officielle du rapport
sur les bibliothèques, rédigé par leur ami commun, l’académicien
Erik Orsenna, avec le concours de Noël Corbin, inspecteur général
des affaires culturelles. L’occasion de présenter les premières
mesures en faveur d’un « plan bibliothèques ».
"""
On utilise alors une expression regulière, ; |, |\' |\n |\s+,pour découper le texte, et conserver les stems dans une liste. C’est ce que réalisera ici la fonction decoupe(texte) :
importredefdecoupe(texte):"""
utilise une expression regulière pour découper le texte (en paramètre) :
- le découpage se fait en fonction de ; ou , ou ' ou \n ou un (ou +) espaces
- on conserve enfin les stems qui font 4 caractères ou plus
la fonction retourne une liste de stems
un stem peut être présent plusieurs fois dans la liste retournée
"""texte_decoupe=list(re.split('; |, |\' |\n |\s+',texte))texte_mini=[]fortintexte_decoupe:match=re.match('[a-z]{4,}',t)ifmatch!=None:texte_mini.append(match.group(0))returntexte_mini
# on créé une liste contenant les articles : col=list(df.keys())# on créé une liste (descriptif) contenant, pour chaque article, une liste avec TOUS les mots retenus dans la descriptiondescriptif=[]forcleincol:desc=df[cle][0]descriptif.append(decoupe(desc))
L’étape suivante consiste à stocker chacune des descriptions traitées sous forme de vecteurs en base de données.
Chaque ligne est un vecteur qui correspond à une description, chaque colonne correspond à un stem.
La fonction mots retourne une liste contenant tous les mots de descriptif, de manière unique. (les mots qui apparaissent plusieurs fois dans descriptif ne sont renvoyés qu’une seule fois dans la liste mot
La fonction tab créé un tableau où les lignes correspondent au nombre d’occurences de ce mot dans la description de l’objet. La ligne de rang 1 correspond aux occurences pour le premier objet de la description, la ligne de rang 2 au 2e objet de la description,…
Pour avoir des valeurs normalisées, on transforme ces occurences en une frequence :
defmots(descriptif):"""
retourne la liste de tous les mots de descriptif, de manière unique, dans une seule liste
"""liste_de_mots=[]fordescindescriptif:foriindesc:ifnot(iinliste_de_mots):liste_de_mots.append(i)returnliste_de_motsmots(descriptif)
deftab(descriptif):"""
retourne la liste tableau avec les occurences pour chaque article (chaque rang)
des mots retenus (mots)
une colonne par mot
"""tableau=[]mots_elements=mots(descriptif)fordescindescriptif:ligne=[]nombre_de_mots=len(desc)ligne=[desc.count(mot)/nombre_de_motsformotinmots_elements]tableau.append(ligne)returntableautableau=tab(descriptif)print(tableau)
La dernière étape est celle du calcul des similarités. Cela consiste à appliquer la similarité cosinus 2 à 2 pour tous les produits de la base de données :
On cherche alors une règle de similitude, du type : A=>B (si on aime A alors on aurait tendance à aussi apprécier B)
importnumpyasnpdefcosij(ui,uj):"""
retourne le resultat du calcul de s_ij pour 2 valeurs ui(i) et uj(j)
paramètres :
les vecteurs ui et uj de modules mod(ui) et mod(uj)
"""s=0foriinrange(len(ui)):s+=ui[i]*uj[i]/(mod(ui)*mod(uj))returnsdefmod(u):"""
calcule le module du vecteur mis en paramètre
"""s=0foriinrange(len(u)):s+=u[i]*u[i]s=s**0.5returnsdefmatrice_cos(A,B):"""
retourne la matrice de similitude entre 2 listes
de dimension 2 (liste de liste), A et B mises en paramètre
"""C=np.zeros(shape=(len(A),len(B)))foriinrange(len(A)):forjinrange(len(B)):C[i,j]=cosij(A[i],B[j])returnCmat=matrice_cos(tableau,tableau)mat
# visualisation du tableau grace à son DataFramedf3=pd.DataFrame(mat,index=col,columns=col)df3
bande dessinee
roman
ordinateur
console de jeux
bande dessinee
1.000000
0.400000
0.091287
0.273861
roman
0.400000
1.000000
0.091287
0.182574
ordinateur
0.091287
0.091287
1.000000
0.500000
console de jeux
0.273861
0.182574
0.500000
1.000000
# visualisation à l'aide d'un outil en couleurimportseabornassnsimportmatplotlib.pyplotaspltcol=list(df3.keys())sns.heatmap(mat,square=True,annot=True,cbar=False,xticklabels=list(col),yticklabels=list(col))
<matplotlib.axes._subplots.AxesSubplot at 0x1a17767250>
# visualisation avec matplotlib (un peu moins lisible)plt.matshow(mat,cmap='rainbow');
Interpretation
On voit assez facilement que :
la bande dessinée est proche dans sa description avec le roman, avec un score de 0.4, et un un peu moins proche de la console de jeux (score de 0.27)
l’ordinateur est compatible avec la console de jeux, avec un score de 0.5
La description de la bande dessinnée et du roman ne contient presque aucun point commun avec l’ordinateur
defarticles(tab):tab=tab.sort_values(ascending=False)articles=list(tab.index.values)recom='l\'article \033[1m {0:15}\033[0;0m est similaire à \033[1m{1:15}\033[0;0m voire peut être un peu à \033[1m{2:15}\033[0;0m'.format(articles[0],articles[1],articles[2])returnrecomdefrecommandation(dataf):texte=[]col=list(dataf.keys())forcincol:tab_red=[]tab_red=dataf[c]texte.append(articles(tab_red))returntextetexte=recommandation(df3)fortintexte:print(t)
l'article bande dessinee est similaire à roman voire peut être un peu à console de jeux
l'article roman est similaire à bande dessinee voire peut être un peu à console de jeux
l'article ordinateur est similaire à console de jeux voire peut être un peu à roman
l'article console de jeux est similaire à ordinateur voire peut être un peu à bande dessinee
definir des classes à l’aide d’une représentation en graphe
importmatplotlib.pyplotaspltimportnetworkxasnxmat=matrice_cos(tableau,tableau)col=list(df3.keys())G=nx.Graph()defmakeG(mat,col):"""
creation du graphe G à partir :
- du paramètre col : la liste des lés (colonnes) du DataFrame fg3 (equiv à la matrice de similitude)
- du paramètre mat : la matrice de similitude déjà calculée
Les noeuds du graphe sont constitués à partir des articles
Les arêtes sont pondérés d'un poids weight qui est la valeur lue dans la matrice de similitude mat
"""foriinrange(len(mat[:,0])):forjinrange(len(mat[0,:])):G.add_edge(col[i],col[j],weight=mat[i,j])returnG#G.add_edge('a', 'b', weight=0.6)defdrawG(G,seuil):"""
segmentation de arêtes en fonction du paramètre seuil
- les arêtes de weight >= seuil sont représentées en trait plein sur le graphe
- celle de weight < seuil sont représentées en trait pointillé
"""elarge=[(u,v)for(u,v,d)inG.edges(data=True)ifd['weight']>=seuil]esmall=[(u,v)for(u,v,d)inG.edges(data=True)ifd['weight']<seuil]pos=nx.spring_layout(G)# positions for all nodes# nodesnx.draw_networkx_nodes(G,pos,node_size=700)# edgesnx.draw_networkx_edges(G,pos,edgelist=elarge,width=6)nx.draw_networkx_edges(G,pos,edgelist=esmall,width=2,alpha=0.5,edge_color='b',style='dashed')# labelsnx.draw_networkx_labels(G,pos,font_size=20,font_family='sans-serif')plt.axis('off')plt.show()G=makeG(mat,col)drawG(G,0.3)
Interprétation
Il apparait ici clairement 2 classes en choisissant seuil = 0.3 :
les articles du genre littérature
les articles du genre électronique
Classification
L’arbre de classification peut être utile dans le cas
L’apprentissage par arbre de décision désigne une méthode basée sur l’utilisation d’un arbre de décision comme modèle prédictif. Dans ces structures d’arbre, les feuilles représentent les valeurs de la variable-cible (les classes) et les embranchements correspondent à des combinaisons de variables d’entrée qui mènent à ces valeurs. En analyse de décision, un arbre de décision peut être utilisé pour représenter de manière explicite les décisions réalisées et les processus qui les amènent.
Une des variables d’entrée est sélectionnée à chaque nœud intérieur (ou interne, nœud qui n’est pas terminal) de l’arbre selon une méthode qui dépend de l’algorithme.
L’arbre est en général construit en séparant l’ensemble des données en sous-ensembles en fonction de la valeur d’une caractéristique d’entrée. Il est construit de manière récursive. C’est un algorithme glouton.
arbres de regression, qui permettent de prédire une quantité réelle
Les algorithmes pour construire les arbres de décision sont construits en divisant l’arbre du sommet vers les feuilles en choisissant à chaque étape une variable d’entrée qui réalise le meilleur partage de l’ensemble d’objets, comme décrit précédemment. Pour choisir la variable de séparation sur un nœud, les algorithmes testent les différentes variables d’entrée possibles et sélectionnent celle qui maximise un critère donné.
Choisir alors le fichier : graphes_mini_prog.ipynb
Définition
Un arbre de classification est utile pour réaliser des prévisions de manière explicite. C’est un outil utilisé
pour les algorithmes de backtracking (modéliser une partie d’echecs)
pour l’appentissage automatisé (machine learning) supervisé (les classes des entrées sont connue)
Pour le machine learning l’arbre peut évoluer et se restructurer à partir d’informations reçues.
A partir des valeurs des données en entrée, l’algorithme va créer des règles pour segmenter, au mieux, la population (les index des entrées) à chaque noeud. En descendant dans l’arbre de classification, on parcourt ses noeuds. Le nombre d’éléments qu’il reste à classer diminue du noeud parent vers un noeud fils : tous les éléments se répartissent sur tous les noeuds fils.
Enfin, lorsque les éléments d’un noeuds ont tous la même classe, alors la division est terminée. Ce noeud est alors une feuille.
Exemple : ici, les noeuds 4, 6, 7, 8, 9, 10 sont des feuilles. Ces noeuds contiennent chacun une partie des éléments qui ont servi à construire l’arbre. La totalité de ces éléments occupent le noeud racine, numéro 0, puis sont répartis dans les feuilles selon leur classe.
Principe
Utilisation de la librairie sklearn pour créer un arbre de classification/décision à partir d’un fichier de données.
L’arbre de decision est construit à partir d’une segmentation optimale qui est réalisée sur les entrées (les lignes du tableau).
Jouer ou ne pas jouer
fichier de données
Ici, le fichier de données est datas/jouer0.png. Il contient les données méteorologiques et les classes (jouer/ne pas jouer au golf) pour plusieurs types de conditions météo (les lignes).
Ce fichier ne devra contenir que des données numériques (mis à part la première ligne, contenant les étiquettes des colonnes, les features).
Classifier puis prédire
Une fois l’arbre de classification établi, on pourra le parcourir pour prédire la classe d’une nouvelle entrée, en fonction de ses valeurs : l’arbre sert alors comme une aide à la décision.
En pratique, il faudra créer une structure qui contient l’arbre, avec ses noeuds, leur association, et les tests qui sont effectués pour descendre d’un noeud parent à l’un des ses noeuds fils. On peut choisir d’utiliser un dictionnaire python pour contenir cette structure. Le dictionnaire étant un tableau associatif.
Comme les données sont toutes numériques, les tests réalisés à chaque noeud, pour traduire la division des éléments s’écrivent de la manière suivante :
Soit X une liste de listes contenant : les éléments à classer, et les valeurs pour chacun des éléments :
X[i] fait alors référence à la valeur des éléments pour la colonne n°i.
pour touts les éléments présents au noeud courant :
si X[i] <= valeur_seuil alors :
descendre vers le noeud fils gauche
sinon : descendre vers le noeud fils droit
Import des librairie et création de l’arbre de décision
fromsklearnimporttreefromsklearn.treeimportDecisionTreeClassifierfromsklearn.treeimportexport_textimportpandasaspddf=pd.read_csv("datas/jouer0.csv",sep=";")#col = df.columnsX=df.iloc[:,:-1]# les données sont toutes les colonnes du tableau sauf la dernièrey=df.iloc[:,-1]# les classes sont dans la dernière colonne (jouer/ne pas jouer)clf=tree.DecisionTreeClassifier()clf=clf.fit(X,y)# on entraine l'arbre à l'aide du jeu de donnéesdf
temps
température
humidité
vent
jouer
0
1
30
85
0
0
1
1
27
90
1
0
2
0
28
78
0
1
3
-1
21
96
0
1
4
-1
20
80
0
1
5
-1
18
70
1
0
6
0
18
65
1
1
7
1
22
95
0
0
8
1
21
70
0
1
9
-1
24
80
0
1
10
1
24
70
1
1
11
0
22
90
1
1
12
0
27
75
0
1
13
-1
22
80
1
0
accéder au paramètres calculés pour l’arbre
# Using those arrays, we can parse the tree structure:n_nodes=clf.tree_.node_countchildren_left=clf.tree_.children_left# noeud fils gauche pour le noeud courant (ou -1 si aucun noeud enfant)children_right=clf.tree_.children_right# noeud fils droit pour le noeud courant (ou -1 si aucun noeud enfant)feature=clf.tree_.feature# numéro de la colonne pour la valeur testée # # par exemple : feature = 0 <=> temps# # par exemple : feature = 1 <=> temperature ... threshold=clf.tree_.threshold# valeur seuil du test realisé au noeud courant
En particulier : on dispose d’une expression en NPI, du type :
L3 = [7,8,'-',6,'*',10,3,'+','*']
Et on veut créer et afficher le graphe correspondant :
On utilisera le script :
L3 = [7,8,'-',6,'*',10,3,'+','*']
D = makeTree(L3)
G = nx.Graph()
graphDict(D)
Dont l’instruction suivante va générer le dictionnaire à partir de l’expression NPI (fonction npiTree recursive):
D = makeTree(L3)
D
# affiche {'*': ({'*': ({'-': (7, 8)}, 6)}, {'+': (10, 3)})}
Ce dictionnaire peut être alors parcouru avec des elgorithmes recursifs, comme par exemple celui de la fonction createEdges qui est un parcours en profondeur.
Le script permet aussi de créer une structure intermédiaire sous forme de dictionnaire, et permet d’afficher le graphe à partir de tout dictionnaire D :
G = nx.Graph()
graphDict(D)
Le graphe est dans le format networkx. On pourra consulter la notice à l’adresse suivante :
defhierarchy_pos(G,root=None,width=1.,vert_gap=0.2,vert_loc=0,xcenter=0.5):'''
From Joel's answer at https://stackoverflow.com/a/29597209/2966723.
Licensed under Creative Commons Attribution-Share Alike
If the graph is a tree this will return the positions to plot this in a
hierarchical layout.
G: the graph (must be a tree)
root: the root node of current branch
- if the tree is directed and this is not given,
the root will be found and used
- if the tree is directed and this is given, then
the positions will be just for the descendants of this node.
- if the tree is undirected and not given,
then a random choice will be used.
width: horizontal space allocated for this branch - avoids overlap with other branches
vert_gap: gap between levels of hierarchy
vert_loc: vertical location of root
xcenter: horizontal location of root
'''ifnotnx.is_tree(G):raiseTypeError('cannot use hierarchy_pos on a graph that is not a tree')ifrootisNone:ifisinstance(G,nx.DiGraph):root=next(iter(nx.topological_sort(G)))#allows back compatibility with nx version 1.11else:root=random.choice(list(G.nodes))def_hierarchy_pos(G,root,width=1.,vert_gap=0.2,vert_loc=0,xcenter=0.5,pos=None,parent=None):'''
see hierarchy_pos docstring for most arguments
pos: a dict saying where all nodes go if they have been assigned
parent: parent of this branch. - only affects it if non-directed
'''ifposisNone:pos={root:(xcenter,vert_loc)}else:pos[root]=(xcenter,vert_loc)children=list(G.neighbors(root))ifnotisinstance(G,nx.DiGraph)andparentisnotNone:children.remove(parent)iflen(children)!=0:dx=width/len(children)nextx=xcenter-width/2-dx/2forchildinchildren:nextx+=dxpos=_hierarchy_pos(G,child,width=dx,vert_gap=vert_gap,vert_loc=vert_loc-vert_gap,xcenter=nextx,pos=pos,parent=root)returnposreturn_hierarchy_pos(G,root,width,vert_gap,vert_loc,xcenter)
importmatplotlib.pyplotaspltimportnetworkxasnximportredefdeversepile(p1,p2):whilep1!=[]:p2.append(p1.pop())returnp2defnpiTree(L):"""transforme l'expression NPI en un dictionnaire
respectant les priorités de calcul
Attention : la liste doit d'abord être mise à l'envers
Utilise un algorithme recursif
Params :
--------
L : list : expression NPI
Returns :
---------
dictionnaire
exemple :
---------
[7,8,'-',6,'*',10,3,'+','*'] => {'*': ({'*': ({'-': (7, 8)}, 6)}, {'+': (10, 3)})}
"""#print('npiTree')iflen(L)==1:# condition d'arret de l'appel recursifreturnL[0]fg=L.pop()fd=L.pop()pere=L.pop()#print('L : {}'.format(L))D={}ifperein['*','+','-']:# données sous la forme : 'op',fg,fdD[pere]=fg,fdL.append(D)else:# données sous la forme : 'op0',('op1',fg1,fd1),fg0 => 'op0',fg0,fg0fg0=fgfg1=fdfd1=perepere1=L.pop()D[pere1]=fg1,fd1L.append(D)L.append(fg0)#print('L : {}'.format(L))returnnpiTree(L)defmakeTree(L_NPI):"""transforme liste issue d'une NPI
en un dictionnaire D
La liste est d'abord mise à l'envers avec deversepile
puis on appelle la fonction npiTree
Params :
--------
L_NPI : liste
Returns :
---------
D : dictionnaire à transformer en graphe
"""D={}p1=[]deversepile(L_NPI,p1)D=npiTree(p1)returnDdefdecoupe(texte):"""transforme la chaine de caractere correspondant au dictionnaire de l'arbre
en une liste
Params :
--------
texte : string : la chaine à découper
Returns :
---------
texte_decoupe : la liste
"""texte_decoupe=list(re.findall('[{}():,*+-]|\w+',texte))returntexte_decoupedefcreerNodes(D):"""modifie la liste ou chaque item (valeur numerique ou operateur) est remplacé par le no de noeud
on créé aussi le noeud et son etiquette à partir de l'item
Params :
--------
D : dict : dictionnaire correspondant a l'arbre
Returns :
---------
eval(chaine) : dict : dictionnaire avec les no de noeud à la place des items
"""texte=decoupe(str(D))index=1fori,cinenumerate(texte):ifc[0]in['*','+','-','0','1','2','3','4','5','6','7','8','9']:G.add_node(index,label=c)texte[i]=str(index)index+=1chaine=''.join(texte)returneval(chaine)defcreateEdges(D,key0=None):"""créé une liste de tuple correspondant aux aretes de l'arbre
l'algorithme utilise un parcours en profondeur recursif et ajoute la nouvelle arete
à une liste LL
Params :
--------
D : dict : represente l'arbre à parcourir
key0 : list ou int : le noeud parent
Returns :
---------
LL[0] : contient un seul element : la liste de toutes le aretes
tous les operateurs sont mis dans une liste de 1 élément. Il faudra sortir ces elements de la liste pour pouvoir
acceder au aretes seuls.
"""ifnotisinstance(D,dict):#print((key0,D))LL.append((key0,D))returnLL[0]else:key=list(D.keys())#return keyifkey0!=None:#print((key0,key))LL.append((key0,key))createEdges(D[key[0]][0],key)createEdges(D[key[0]][1],key)defgraphDict(D):"""construction du graphe G au format de la lib networkx
et affiche le graphe
Params :
--------
D : dict issu de la chaine NPI ou autre
Returns :
---------
G : graphe format networkx
"""Dnum=creerNodes(D)globalLL# necessaire pour utiliser LL dans la fonction createEdges recursiveLL=[]createEdges(Dnum)# arranger le format des elements de la liste d'aretes (suprimer le format list de certains elements)fori,cinenumerate(LL):c0=c[0]c1=c[1]ifisinstance(c0,list):c0=c[0][0]ifisinstance(c1,list):c1=c[1][0]c=c0,c1LL[i]=c#print(LL) # Dict d'etiquette des noeudsliste=list(G.nodes(data='label'))labels_nodes={}fornoeudinliste:labels_nodes[noeud[0]]=noeud[1]#labels_nodesG.root=1G.add_edges_from(LL)#print(list(G.edges()))pos1=hierarchy_pos(G,G.root)nx.draw(G,pos=pos1,labels=labels_nodes,with_labels=True,font_size=15,font_family='sans-serif',node_color='pink',alpha=0.9)plt.savefig('datas/NPI1.png')plt.show()returnG
Puis choisir : gestionBase_de_donnees_python.ipynb
Exercez vous en suivant le tutoriel avec ce notebook.
présentation
Pandas fournit des structures de données puissantes et simples à utiliser, ainsi que les moyens d’opérer rapidement des opérations sur ces structures.
Cette librairie va utiliser et faire des opérations sur un objet : le DataFrame
Ce DataFrame est très similaire aux tables des bases de données relationnelles (type MySQL, PostgreSQL, etc.) que l’on manipule grâce au langage SQL.
représentation d’un tableau avec la librairie numpy
numpy est une librairie utile pour de nombreuses applications mathématiques. numpy permet de manipuler facilement des tableaux. Un tableau est une liste contenant une nouvelle liste pour chacun de ses éléments. C’est une liste de listes.
L’avantage de manipuler des tableaux, (array), plutôt que des listes, c’est de pouvoir réaliser des calculs sur les valeurs comme si la structure de donnée était une matrice.
On va voir ici que cette représentation des données n’est pas la meilleure façon qu’il soit lorsqu’on l’utilise pour une collection (par exemple pour des informations).
Prenons l’exemple de la programmation d’une salle de cinéma de type cinémathèque :
On renseigne pour chacune des salles de ce cinéma (pour chacune des lignes), les valeurs : le titre du film (colonne 1), horaire (colonne 2), realisateur (col 3), année (col 4).
#************************************##****** un premier exemple **********##******* de numpy à panda ***********##************************************#importnumpyasnptableau2D=[['la rage aux poings','18h00','Eric le Hung',1975],# film projeté dans la salle 1['le million','15h00','René Clair',1931],# dans la salle 2['Rendez vous à Badenberg','21h00','René Meurice',1970],# dans la salle 3['Le cercle rouge','18h05','Jean-Pierre Melville',1970],# dans la salle 4]tableau_numpy=np.array(tableau2D)tableau_numpy
# acceder à l'élément de rang 3 de la ligne 0 : tableau_numpy[0,3]
# acceder à TOUS les elements au rang 0 (donc la première colonne)tableau_numpy[:,0]
C’est assez pratique certes, mais tableau_numpy[:, 0] quand cette colonne possède un descripteur (le nom du film), ce n’est pas très explicite.
On va voir maintenant ce qu’apporte la représentation des données avec la librairie Pandas.
représentation des données avec la librairie pandas
Les données sont maintenant mises dans un DataFrame, et plus un tableau array.
#***************************##**** creer un DataFrame ***##***************************#importpandasaspd# on importe la librairie pandastableau2D_df=pd.DataFrame(tableau2D)# on créé un DataFrame tableau2D_df à partir de l'array tableau2Dtableau2D_df# et on l'affiche
#******************************************##********** passage du tableau np *********##*** ainsi que les index et descripteurs **##******************************************#tableau2D_df=pd.DataFrame(tableau_numpy,index=['salle 1','salle 2','salle 3','salle 4'],columns=['titre','horaire','realisateur','année'])tableau2D_df
On peut maintenant réduire le tableau en une seule colonne, par exemple celle dont l’etiquette est horaire. On obtient alors une serie de données.
# reduire le tableau (SELECT)tableau2D_df.horaire# 1ere methodetableau2D_df['horaire']# 2e methode
Et si l’on a besoin d’une série comprenant 2 colonnes (ou plus), on utilise la syntaxe suivante :
tableau2D_df[["titre","horaire"]]
parcours et exploration des données
On peut utiliser une boucle bornée qui, à chaque itération, donne :
l’indice
le contenu de la serie pour cet index (c’est à dire les valeurs et leur etiquette pour chacun des objets)
On utilise la fonction iterrow associée au DataFrame :
for index, valeurs in DataFrame.iterrows() :
...
# parcourirforind_ligne,contenu_ligneintableau2D_df.iterrows():print("Voici le film de la %s :"%ind_ligne)print(contenu_ligne)print("--------------------")
accéder à un seul des objets de la collection
Cette fois, plutôt que d’utiliser une boucle bornée et d’afficher TOUS les objets de la collection, on cherche à en afficher un seul.
Cette fois le tri ne se fait pas selon une colonne, comme par exemple pour tableau2D_df['horaire'] mais par ligne, avec :
`tableau_2D_df.loc[‘salle 3’] par exemple
On aura ainsi le descriptif du film programmé dans cette salle.
# acceder à un objettableau2D_df.iloc[2]# Avec iloc(), indexation positionnelletableau2D_df.loc["salle 3"]# Avec loc(), indexation par label
Rechercher un film
On va maintenant trier le tableau jusqu’à trouver l’élement correspondant.
On cherche par exemple, dans quelle salle passe le film ‘Rendez vous à Badenberg’ : La colonne correspondant à cette valeur est celle dont l’etiquette est 'titre'. On écrit alors une expression logique, qui est évaluée pour chaque objet, et qui renvoie true si le titre correspond à celui recherché, et false sinon.
La console affiche alors une serie de données :
# trier (WHERE)tableau2D_df["titre"]=='Rendez vous à Badenberg'
Question : Ecrire l’instruction qui renverra true pour toutes les salles projettant un film réalisé en 1970.
Testez votre instruction dans la cellule suivante.
filtrer les données du tableau
On va maintenant appliquer l’expression logique vue plus haut pour reduire le DataFrame aux seuls objets pour lesquels l’expression renvoie true. On dit que l’on a filtré les données.
Premier exemple : filtrage du tableau pour ne conserver que la salle dans laquelle passe le film ‘Rendez vous à Badenberg’. On obtient alors un nouveau DataFrame, mais réduit.
# masquer (WHERE)tableau_filtre=tableau2D_df[tableau2D_df["titre"]=='Rendez vous à Badenberg']tableau_filtre# on affiche le tableau filtré
Exemple 2 : on cherche le complémentaire de l’expression precedente : filtrer et renvoyer tous les films DIFFERENTS de *`Rendez vous à Badenberg’
On utilise pour cela le symbole ~ (tild) devant l’expression dont on veut le complémentaire :
tableau_comp=tableau2D_df[~(tableau2D_df["titre"]=='Rendez vous à Badenberg')]tableau_comp
Exemple 3 : filtrer par rapport aux dates de réalisation.
Travail : ecrire l’instruction qui renvoie un nouveau DataFrame, mais uniquement avec des films réalisés en 1970
trier le tableau
On peut vouloir maintenant afficher les films dans l’ordre croissant de diffusion dans la journée.
Pour des raisons de commodité, on modifie le format de l’heure de diffusion pour que le type de données soit float et non str. Par exemple : ‘18h00’ => 18.00
tableau2D_df['horaire']=[18,15,20,18.1]tableau2D_df# on affiche le tableau
On peut maintenant trier ce tableau selon l’horaire :
tableau2D_df.sort_values(by='horaire')
Et voilà, vous n’avez plus aucun excuse pour rater une seance ;-)
Traitement de données en csv
Le fichier joint joueursNBA2020.csv est un extrait des joueurs professionnels de basket de NBA, pour la saison 2019-2020. On va utiliser la librairie pandas pour ouvrir puis explorer ce fichier.
Les données recupérées doivent souvent être remises en forme. Le tableau ci-dessus présente plusieurs problèmes qui doivent être traités avant de pouvoir exploiter les données :
Il y a des colonnes Unnamed qui ne servent à rien : elles seront à supprimer
Il y a plus de lignes que de joueurs. Ces lignes ont pour valeur NaN. Il faudra aussi les supprimer.
Le poids des joueurs, dans la colonne ‘poids’ est exprimé sous format str. Les valeurs sont écrites avec l’unité, kg. Il vaudra mieux les tranformer en type float, en retirant les caractères kg.
#***************************************## en pratique **************************## selection des colonnes renseignées ## et suppression des lignes NaN ## avec .dropna() ##***************************************#tableau_reduit=data[['nom','equipe','poste','taille','poids','experience','pays']].dropna()
#*************************************## puis `cast` de la colonne poids ## les valeurs sont de type str et ## combinent des float avec kg ## par exemple 89.8 kg ##*************************************#tableau_reduit['poids']=tableau_reduit['poids'].replace(to_replace='kg',value='',regex=True)
#************************************## puis conversion du type ## str vers float ## **********CAST ********************##************************************#tableau_reduit['poids']=tableau_reduit['poids'].astype('float')
tableau_reduit.loc[1]['poids']
tableau_reduit
Et voila, il n’y a plus qu’à explorer ce tableau de données. On peut par exemple :
filtrer le tableau pour n’afficher que les joueurs du poste ‘C’
filtrer les joueurs pour ne conserver que les joueurs de nationalité autre que americaine.
Trier les joueurs par taille, ou par poids
Travail : Testez certaines des propositions faites ici…
Les scripts suivants permettent de choisir entre plusieurs types de configuration pour tracer un graphe avec Networkx, module Python.
On pourra choisir de personaliser :
la couleur d’un noeud
l’etiquette des noeuds
l’étiquette des arêtes
le type de trait (plein ou en pointillés) des arêtes
Déclaration du graphe
importmatplotlib.pyplotaspltimportnetworkxasnxfromnumpyimportarrayG=nx.Graph()# definition des noeudsG.add_node(0,label='A',col='pink')G.add_node(1,label='B',col='red')G.add_node(2,label='C',col='white')G.add_node(3,label='D',col='white')G.add_node(4,label='E',col='white')G.add_node(5,label='F',col='blue')# definition des aretesG.add_edge(0,1,weight=6,styl='dashed')G.add_edge(0,2,weight=5,styl='solid')G.add_edge(0,4,weight=1,styl='solid')G.add_edge(4,1,weight=5,styl='solid')G.add_edge(4,2,weight=1,styl='solid')G.add_edge(4,3,weight=3,styl='solid')G.add_edge(2,3,weight=8,styl='solid')G.add_edge(4,5,weight=6,styl='dashed')G.add_edge(3,5,weight=9,styl='solid')
# positions for all nodespos=nx.spring_layout(G)# nodesnx.draw_networkx_nodes(G,pos,node_size=700,node_color=colorList,alpha=0.9)# labelsnx.draw_networkx_labels(G,pos,labels=labels_nodes, \
with_labels=True,font_size=20, \
font_color='black', \
font_family='sans-serif')# edgesnx.draw_networkx_edges(G,pos,width=1)nx.draw_networkx_edge_labels(G,pos,width=1,edge_labels=labels_edges,style='dashed',font_color='red')plt.axis('off')plt.savefig('datas/fig1.png')plt.show()
Utilisation d’une fonction multitracés
fonction multigraphes
defmultigraphe(G,pos,name,edg=True,dashed=False):"""
tracé d'un graphe G à partir des options obligatoires :
label et col pour G.nodes :
G.add_node(0,label='A',col='pink')
weight et styl pour G.edges :
G.add_edge(0,1,weight=6,styl='dashed')
Params :
--------
G : graphe
pos : un dictionnaire qui contient les positions des différents noeuds
obtenu à partir de : pos = nx.spring_layout(G)
name : chaine de caractères finissant par l'extension .png par ex monfichier.png
edg : option pour affichage des etiquettes sur les aretes
par defaut edg vaut 'True' et l'etiquette EST affichée ('False' sinon)
dashed : option pour tracer un graphe en solid + en pointillé avec l'option styl de G.edges
"""# liste de couleurs pour les noeudsliste=list(G.nodes(data='col'))colorNodes={}fornoeudinliste:colorNodes[noeud[0]]=noeud[1]colorList=[colorNodes[node]fornodeincolorNodes]# Dict d'etiquette des noeudsliste=list(G.nodes(data='label'))labels_nodes={}fornoeudinliste:labels_nodes[noeud[0]]=noeud[1]# Dict d'etiquette des areteslabels_edges={}ifedg:labels_edges={edge:G.edges[edge]['weight']foredgeinG.edges}else:labels_edges={edge:''foredgeinG.edges}# Division en 2 des aretes : solid et dashedelarge=[(u,v)for(u,v,w)inG.edges(data=True)ifw['styl']=='solid']esmall=[(u,v)for(u,v,w)inG.edges(data=True)ifw['styl']=='dashed']# positions for all nodes : # à mettre en parametre pour que chaque graphe ait la même disposition# pos = nx.spring_layout(G) # nodesnx.draw_networkx_nodes(G,pos,node_size=700,node_color=colorList,alpha=0.9)# labelsnx.draw_networkx_labels(G,pos,labels=labels_nodes, \
with_labels=True,font_size=20, \
font_color='black', \
font_family='sans-serif')# edgesifdashed:nx.draw_networkx_edges(G,pos,edgelist=elarge,width=3)nx.draw_networkx_edges(G,pos,edgelist=esmall,width=3,alpha=0.5,edge_color='b',style='dashed')else:nx.draw_networkx_edges(G,pos,width=1)nx.draw_networkx_edge_labels(G,pos,width=1,edge_labels=labels_edges,font_color='red')plt.axis('off')fichier='datas/'+nameplt.savefig(fichier)plt.show()
Les scripts suivants permettent de créer un labyrinthe de manière aléatoire, et d’exploiter la structure de données de ce labyrinthe. On pourra ainsi tester quelques algorithmes relatifs au parcours de ce labyrinthe.
Les scripts en permettent une visualisation.
defdirections(laby,i,j):"""les directions possibles pour la case courante
i : int numero de ligne
j : numero de la colonne
retourne une liste (tuple) des points cardinaux possibles
"""L=[]iflaby.tab[j][i].N==True:L.append('N')iflaby.tab[j][i].S==True:L.append('S')iflaby.tab[j][i].E==True:L.append('E')iflaby.tab[j][i].W==True:L.append('W')returntuple(L)
Un labyrinthe est un tableau de cases laby.tab[j][i] ayant chacune pour propriétés : N,S,E,W
i : int numero de ligne
j : numero de la colonne
Pour chacune de ces propriétés, par exemple laby.tab[j][i].Non renseigne une valeur True ou False
True : direction possible
False : impossible (mur)
Créer un labyrinthe vide
deflabyrinthe(lines,col):"""
Params :
--------
lines : int : nombre de lignes du labyrinthe
col : int : nombre de colonnes
Returns :
---------
tab2 : list : tuples de 1 à 4 éléments correspondants aux directions libres ('N', 'S', E', 'W')
sortie : tracé du labyrinthe
Variables :
-----------
p : nombre de colonnes (=largeur)
q : nombre de lignes (=hauteur)
"""laby=creation(col,lines)tab2=[[0]*laby.pforiinrange(laby.q)]foriinrange(laby.q):forjinrange(laby.p):tab2[i][j]=directions(laby,i,j)Labyrinthe.show(laby)returntab2tab=labyrinthe(5,6)
Remarque : Les lignes sont mises dans l’ordre inverse du dessin du labyrinthe :
Tracé du labyrinthe
defmur(dir,i,j):"""trace les murs des directions fermées
dir est un tuple contenant les directions libres
"""line=10ifnot('N'indir[i][j]):plt.plot([j,j+1],[i+1,i+1],'black',linewidth=line)ifnot('S'indir[i][j]):plt.plot([j,j+1],[i,i],'black',linewidth=line)ifnot('E'indir[i][j]):plt.plot([j+1,j+1],[i,i+1],'black',linewidth=line)ifnot('W'indir[i][j]):plt.plot([j,j],[i,i+1],'black',linewidth=line)defmurs(tab):foriinrange(len(tab)):forjinrange(len(tab[i])):mur(tab,i,j)plt.plot([0,0,len(tab[0]),len(tab[0]),0],[0,len(tab),len(tab),0,0],'blue',linewidth=10)plt.savefig('labyrinthe.png')
On peut faire l’économie du tracé eventuel côté S et côté W grace au tracé des cases adjacentes.
murs(tab)
Parcours du labyrinthe
fonctions utiles
defnexto(c,direc):"""retourne les coordonnées lors du deplacement
selon la position actuelle et la direction
Params :
--------
c : tuple (ligne,colonne) correspondant à (y,x) dans le plan cartesien
direct : str : 'N', 'S', E', 'W'
Returns :
---------
tuple : (int,int) correspondant à (ligne,colonne)
"""i,j=c[0],c[1]ifdirec=='N':return(i+1,j)ifdirec=='S':return(i-1,j)ifdirec=='E':return(i,j+1)ifdirec=='W':return(i,j-1)defvisited(c,L,couleur):"""retourne la couleur du noeud de coord c et
de liste de directions possibles L selon celle de ses voisins
Params :
--------
c : tuple : (ligne,colonne) correspondant à (y,x) dans le plan cartesien
L : list : tuples de 1 à 4 éléments correspondants aux directions libres ('N', 'S', E', 'W')
couleur : List dimension 2 contenant des elements str
'white' si noeud non visité,
'green' si le noeud est en cours de visite,
'red' si tous les noeuds ont été visités autour de lui
Returns :
---------
couleur : str : 'green' si le noeud est en cours de visite, 'red' si tous les noeuds
ont été visités autour de lui
"""i,j=c[0],c[1]coul='red'fordirecinL:coord=nexto(c,direc)ifcouleur[coord[0]][coord[1]]=='white':coul='green'print(c,coul)returncoul
une premiere idée : colorer les noeuds du chemin en vert
deftrouvercheminiter(start,end,tab):"""recherche du chemin jusqu'à la sortie dans le labyrinthe
en utilisant une technique qui s'apparente au parcours en profondeur
avec backtracking
on utilise une pile de noeuds visités
Params :
--------
start : tuple de coord dans le labyrinthe
end : tuple de coord dans le labyrinthe
tab : liste de liste contenant pour chaque tuple de coordonnées un tuple de directions possibles
Variables :
-----------
couleur : une table de la couleur du noeud ('red' si aucune nouvelle direction possible,
'green' si en cours de visite, 'white' si jamais visité)
Returns:
--------
la liste couleur
"""p=Pile()p.push(start)c=startcouleur=[['white']*len(tab[0])foriinrange(len(tab))]# precaution pour eviter debordementcompt=0while(notp.empty())and(notc==end)andcompt<100:compt+=1c=p.pop()L=tab[c[0]][c[1]]couleur[c[0]][c[1]]=visited(c,L,couleur)# c est retiré de la pile et coloré en green ou redfordirecinL:coord=nexto(c,direc)ifcouleur[coord[0]][coord[1]]=='white':# le noeud fils est coloré en blanc dans la direction Dfornintab[coord[0]][coord[1]]:p.push(coord)# alors on ajoute le noeud fils dans la direction D au sommet de la pile# n fois afin de reconsidérer sa couleur à chaque fois que l'on depilereturncouleur
(4, 0) green
(3, 0) green
(2, 0) green
(2, 1) green
(3, 1) green
(4, 1) green
(4, 2) green
(4, 3) green
(4, 4) green
(3, 4) green
(3, 5) green
(4, 5) red
(3, 5) red
(3, 4) red
(4, 4) red
(3, 3) green
(3, 2) green
(2, 2) green
(1, 2) green
(1, 1) green
(0, 1) green
(0, 2) green
(0, 3) green
(0, 4) green
(0, 5) green
[['white', 'green', 'green', 'green', 'green', 'green'],
['white', 'green', 'green', 'white', 'white', 'white'],
['green', 'green', 'green', 'white', 'white', 'white'],
['green', 'green', 'green', 'green', 'red', 'red'],
['green', 'green', 'green', 'green', 'red', 'red']]
Une autre approche : mémoriser les étapes de la solution
defsolution(start,end,tab):"""trouve la solution au labyrinthe et trace ce chemin
La recherche du chemin jusqu'à la sortie dans le labyrinthe
utilise une technique qui s'apparente au parcours en profondeur
avec backtracking
on utilise une pile de noeuds visités
Params :
--------
start : tuple de coord dans le labyrinthe
end : tuple de coord dans le labyrinthe
tab : liste de liste contenant pour chaque tuple de coordonnées un tuple de directions possibles
Returns:
--------
la liste couleur
Variables :
-----------
couleur : une table de la couleur du noeud ('red' si aucune nouvelle direction possible,
'green' si en cours de visite, 'white' si jamais visité)
p : Pile() utile pour la recherche du parcours
pchemin : Pile() utile pour memoriser ce chemin
"""p=Pile()pchemin=Pile()p.push(start)c=startcouleur=[['white']*len(tab[0])foriinrange(len(tab))]while(notp.empty())and(notc==end):c=p.pop()pchemin.push(c)L=tab[c[0]][c[1]]couleur[c[0]][c[1]]=visited(c,L,couleur)# c est retiré de la pile et coloré en green ou rednoeud=pchemin.pop()whilecouleur[noeud[0]][noeud[1]]=='red':noeud=pchemin.pop()# il peut y avoir plusieurs fois le noeud successivement dans la pilepchemin.push(noeud)# on remet le dernier noeud retiré non rougefordirecinL:coord=nexto(c,direc)ifcouleur[coord[0]][coord[1]]=='white':# le noeud fils est coloré en blanc dans la direction D#for n in tab[coord[0]][coord[1]]:p.push(c)p.push(coord)# alors on ajoute le noeud fils dans la direction D au sommet de la pile# ainsi que son noeud parentreturnpchemin.lstdefmurSolution(tab,L):xList=[]yList=[]foriinrange(len(tab)):forjinrange(len(tab[i])):mur(tab,i,j)plt.plot([0,0,len(tab[0]),len(tab[0]),0],[0,len(tab),len(tab),0,0],'blue',linewidth=10)forninrange(len(L)):yList.append(L[n][0]+0.5)xList.append(L[n][1]+0.5)plt.plot(xList,yList,'red',linewidth=2)
L=solution((len(tab)-1,0),(0,len(tab[0])-1),tab)L
(4, 0) green
(3, 0) green
(2, 0) green
(2, 1) green
(3, 1) green
(4, 1) green
(4, 2) green
(4, 3) green
(4, 4) green
(3, 4) green
(3, 5) green
(4, 5) red
(3, 5) red
(3, 4) red
(4, 4) red
(4, 3) green
(3, 3) green
(3, 2) green
(2, 2) green
(1, 2) green
(1, 1) green
(0, 1) green
(0, 2) green
(0, 3) green
(0, 4) green
(0, 5) green
[(4, 0),
(3, 0),
(2, 0),
(2, 1),
(3, 1),
(4, 1),
(4, 2),
(4, 3),
(4, 3),
(3, 3),
(3, 2),
(2, 2),
(1, 2),
(1, 1),
(0, 1),
(0, 2),
(0, 3),
(0, 4),
(0, 5)]
murSolution(tab,L)
mémoriser TOUTES les étapes du parcours
defparcours(start,end,tab):"""trouve la solution au labyrinthe et trace ce chemin
p : Pile() utile pour la recherche du parcours
pchemin : Pile() utile pour memoriser tout le chemin
on insère dans le chemin toutes les arêtes empruntées :
pour le chemin entre c1 et c2, on insère c1 puis c2
"""p=Pile()pchemin=Pile()p.push(start)c=startcouleur=[['white']*len(tab[0])foriinrange(len(tab))]while(notp.empty())and(notc==end):c=p.pop()pchemin.push(c)# chaque fois que l'on depile, on rempile dans pcheminL=tab[c[0]][c[1]]couleur[c[0]][c[1]]=visited(c,L,couleur)# c est retiré de la pile et coloré en green ou redfordirecinL:coord=nexto(c,direc)ifcouleur[coord[0]][coord[1]]=='white':# le noeud fils est coloré en blanc dans la direction Dp.push(c)# on remet le noeud parent afin de reconsidérer sa couleur à chaque fois que l'on depile# et le chemin arriere CONTINU pour le tracép.push(coord)# alors on ajoute le noeud fils dans la direction D au sommet de la pilereturnpchemin.lst
L=parcours((len(tab)-1,0),(0,len(tab[0])-1),tab)L
(4, 0) green
(3, 0) green
(2, 0) green
(2, 1) green
(3, 1) green
(4, 1) green
(4, 2) green
(4, 3) green
(4, 4) green
(3, 4) green
(3, 5) green
(4, 5) red
(3, 5) red
(3, 4) red
(4, 4) red
(4, 3) green
(3, 3) green
(3, 2) green
(2, 2) green
(1, 2) green
(1, 1) green
(0, 1) green
(0, 2) green
(0, 3) green
(0, 4) green
(0, 5) green
[(4, 0),
(3, 0),
(2, 0),
(2, 1),
(3, 1),
(4, 1),
(4, 2),
(4, 3),
(4, 4),
(3, 4),
(3, 5),
(4, 5),
(3, 5),
(3, 4),
(4, 4),
(4, 3),
(3, 3),
(3, 2),
(2, 2),
(1, 2),
(1, 1),
(0, 1),
(0, 2),
(0, 3),
(0, 4),
(0, 5)]
murSolution(tab,L)
Python turtle Labyrinthe
Utiliser le module turtle
Le script suivant présente les classes et fonctions utiles pour :
tracer un labyrinthe complet
parcourir le labyrinthe selon une méthode de parcours en profondeur
classPile:def__init__(self):self.lst=[]defempty(self):returnself.lst==[]defpush(self,x):self.lst.append(x)defpop(self):ifself.empty():raiseValueError("pile vide")returnself.lst.pop()"""
def explorer(laby):
pile = Pile()
pile.push((0, laby.q - 1))
laby.tab[0][laby.q - 1].etat = False
while True:
i, j = pile.pop()
if i == laby.p - 1 and j == 0:
break
if j > 0 and laby.tab[i][j].S and laby.tab[i][j-1].etat:
pile.push((i, j))
pile.push((i, j-1))
laby.tab[i][j-1].etat = False
elif i < laby.p-1 and laby.tab[i][j].E and laby.tab[i+1][j].etat:
pile.push((i, j))
pile.push((i+1, j))
laby.tab[i+1][j].etat = False
elif j < laby.q-1 and laby.tab[i][j].N and laby.tab[i][j+1].etat:
pile.push((i, j))
pile.push((i, j+1))
laby.tab[i][j+1].etat = False
elif i > 0 and laby.tab[i][j].W and laby.tab[i-1][j].etat:
pile.push((i, j))
pile.push((i-1, j))
laby.tab[i-1][j].etat = False
return pile.lst
"""classCase:def__init__(self):self.N=Falseself.W=Falseself.S=Falseself.E=Falseself.etat=FalseclassLabyrinthe:def__init__(self,p,q):self.p=pself.q=qself.tab=[[Case()forjinrange(q)]foriinrange(p)]defshow(self):plt.plot([0,0,self.p,self.p,0],[0,self.q,self.q,0,0],linewidth=2)foriinrange(self.p-1):forjinrange(self.q):ifnotself.tab[i][j].E:plt.plot([i+1,i+1],[j,j+1],'b')forjinrange(self.q-1):foriinrange(self.p):ifnotself.tab[i][j].N:plt.plot([i,i+1],[j+1,j+1],'b')plt.axis([-1,self.p+1,-1,self.q+1])plt.show()"""
def solution(self):
sol = explorer(self)
X, Y = [], []
for (i, j) in sol:
X.append(i+.5)
Y.append(j+.5)
X.append(self.p-.5)
Y.append(.5)
plt.plot(X, Y, 'r', linewidth=2)
self.show()
"""defcreation(p,q):laby=Labyrinthe(p,q)pile=Pile()i,j=randint(p),randint(q)pile.push((i,j))laby.tab[i][j].etat=Truewhilenotpile.empty():i,j=pile.pop()v=[]ifj<q-1andnotlaby.tab[i][j+1].etat:v.append('N')ifi>0andnotlaby.tab[i-1][j].etat:v.append('W')ifj>0andnotlaby.tab[i][j-1].etat:v.append('S')ifi<p-1andnotlaby.tab[i+1][j].etat:v.append('E')iflen(v)>1:pile.push((i,j))iflen(v)>0:c=v[randint(len(v))]ifc=='N':laby.tab[i][j].N=Truelaby.tab[i][j+1].S=Truelaby.tab[i][j+1].etat=Truepile.push((i,j+1))elifc=='W':laby.tab[i][j].W=Truelaby.tab[i-1][j].E=Truelaby.tab[i-1][j].etat=Truepile.push((i-1,j))elifc=='S':laby.tab[i][j].S=Truelaby.tab[i][j-1].N=Truelaby.tab[i][j-1].etat=Truepile.push((i,j-1))else:laby.tab[i][j].E=Truelaby.tab[i+1][j].W=Truelaby.tab[i+1][j].etat=Truepile.push((i+1,j))returnlaby
autres definitions utiles
defdirections(laby,i,j):"""les directions possibles pour la case courante
i : int numero de ligne
j : numero de la colonne
retourne une liste (tuple) des points cardinaux possibles
"""L=[]iflaby.tab[j][i].N==True:L.append('N')iflaby.tab[j][i].S==True:L.append('S')iflaby.tab[j][i].E==True:L.append('E')iflaby.tab[j][i].W==True:L.append('W')returntuple(L)deflabyrinthe(lines,col):"""
Params :
--------
lines : int : nombre de lignes du labyrinthe
col : int : nombre de colonnes
Returns :
---------
tab2 : list : tuples de 1 à 4 éléments correspondants aux directions libres ('N', 'S', E', 'W')
sortie : tracé du labyrinthe
Variables :
-----------
p : nombre de colonnes (=largeur)
q : nombre de lignes (=hauteur)
"""laby=creation(col,lines)tab2=[[0]*laby.pforiinrange(laby.q)]foriinrange(laby.q):forjinrange(laby.p):tab2[i][j]=directions(laby,i,j)Labyrinthe.show(laby)returntab2defnexto(c,direc):"""retourne les coordonnées lors du deplacement
selon la position actuelle et la direction
Params :
--------
c : tuple (ligne,colonne) correspondant à (y,x) dans le plan cartesien
direct : str : 'N', 'S', E', 'W'
Returns :
---------
tuple : (int,int) correspondant à (ligne,colonne)
"""i,j=c[0],c[1]ifdirec=='N':return(i+1,j)ifdirec=='S':return(i-1,j)ifdirec=='E':return(i,j+1)ifdirec=='W':return(i,j-1)defvisited(c,L,couleur):"""retourne la couleur du noeud de coord c et
de liste de directions possibles L selon celle de ses voisins
Params :
--------
c : tuple : (ligne,colonne) correspondant à (y,x) dans le plan cartesien
L : list : tuples de 1 à 4 éléments correspondants aux directions libres ('N', 'S', E', 'W')
couleur : List dimension 2 contenant des elements str
'white' si noeud non visité,
'green' si le noeud est en cours de visite,
'red' si tous les noeuds ont été visités autour de lui
Returns :
---------
couleur : str : 'green' si le noeud est en cours de visite, 'red' si tous les noeuds
ont été visités autour de lui
"""i,j=c[0],c[1]coul='red'fordirecinL:coord=nexto(c,direc)ifcouleur[coord[0]][coord[1]]=='white':coul='green'#print(c,coul)returncouldefparcours(start,end,tab):"""trouve la solution au labyrinthe et trace ce chemin
p : Pile() utile pour la recherche du parcours
pchemin : Pile() utile pour memoriser tout le chemin
on insère dans le chemin toutes les arêtes empruntées :
pour le chemin entre c1 et c2, on insère c1 puis c2
"""p=Pile()pchemin=Pile()p.push(start)c=startcouleur=[['white']*len(tab[0])foriinrange(len(tab))]while(notp.empty())and(notc==end):c=p.pop()pchemin.push(c)# chaque fois que l'on depile, on rempile dans pcheminL=tab[c[0]][c[1]]couleur[c[0]][c[1]]=visited(c,L,couleur)# c est retiré de la pile et coloré en green ou redfordirecinL:coord=nexto(c,direc)ifcouleur[coord[0]][coord[1]]=='white':# le noeud fils est coloré en blanc dans la direction Dp.push(c)# on remet le noeud parent afin de reconsidérer sa couleur à chaque fois que l'on depile# et le chemin arriere CONTINU pour le tracép.push(coord)# alors on ajoute le noeud fils dans la direction D au sommet de la pilereturnpchemin.lst
fonctions particulières au module turtle
defturtleWall(dir,i,j):"""trace les murs des directions fermées
dir est un tuple contenant les directions libres
"""larg=len(tab[0])haut=len(tab)fenX=600fenY=fenX*haut/largscaleX=(fenX-20)/largscaleY=(fenY-20)/hautx0=-fenX/2+10y0=-fenY/2+10ifnot('N'indir[i][j]):turtle.penup()turtle.setpos(x0+j*scaleX,y0+(i+1)*scaleY)turtle.setheading(0)turtle.pendown()turtle.forward(scaleX)ifnot('S'indir[i][j]):turtle.penup()turtle.setpos(x0+j*scaleX,y0+i*scaleY)turtle.setheading(0)turtle.pendown()turtle.forward(scaleX)ifnot('E'indir[i][j]):turtle.penup()turtle.setpos(x0+(j+1)*scaleX,y0+i*scaleY)turtle.setheading(90)turtle.pendown()turtle.forward(scaleY)ifnot('W'indir[i][j]):turtle.penup()turtle.setpos(x0+j*scaleX,y0+i*scaleY)turtle.setheading(90)turtle.pendown()turtle.forward(scaleY)defturtleLab(tab):foriinrange(len(tab)):forjinrange(len(tab[i])):turtleWall(tab,i,j)#plt.plot([0, 0, len(tab[0]), len(tab[0]), 0], [0, len(tab), len(tab), 0, 0], 'blue',linewidth=10)#plt.savefig('laby.png')defturtlePath(tab,L):"""tracé du parcours dans le labyrinthe à l'aide de la tortue
Params:
-------
tab : Liste de liste contenant des str : 'N','S','W','E' = le labyrinthe
L : Liste de tuples correspondant aux cases visitées
sortie :
--------
le dessin du parcours animé
"""larg=len(tab[0])haut=len(tab)fenX=600fenY=fenX*haut/largscaleX=(fenX-20)/largscaleY=(fenY-20)/hautx0=-fenX/2+10y0=-fenY/2+10turtle.penup()turtle.pencolor("red")turtle.setpos(x0+scaleX/2,y0+scaleY*4+scaleY/2)# departturtle.showturtle()turtle.pendown()start=L[0]forcinL[1:]:#angle = 90*(c[0]-start[0]) # si deplacement uniquement verticalifc[0]!=start[0]:depl=scaleY# verticalangle=90*(c[0]-start[0])else:depl=scaleX# horizontalangle=90-90*(c[1]-start[1])ifc[1]<start[1]:angle=180# deplacement à gaucheturtle.setheading(angle)turtle.forward(depl)start=c
fonction principale pour affichage de l’animation turtle
defafficheTurtle(tab,L):larg=len(tab[0])haut=len(tab)fenX=600fenY=fenX*haut/largscaleX=(fenX-20)/largscaleY=(fenY-20)/hautturtle.setup(fenX,fenY)#Largeur : 600px, Hauteur : 400pxturtle.bgcolor((0.9,0.9,0.9))turtle.hideturtle()turtle.penup()turtle.setpos(-fenX/2+10,-fenY/2+10)turtle.setheading(90)turtle.pendown()#turtle.speed(0)turtle.tracer(False)# tracer le Laby avant de demarrer l'animation avec la tortueturtle.pensize(2)turtle.forward(fenY-20)turtle.left(-90)turtle.forward(fenX-20)turtle.left(-90)turtle.forward(fenY-20)turtle.left(-90)turtle.forward(fenX-20)turtle.left(-90)turtleLab(tab)turtle.tracer(True)# fin du tracé du Labyturtle.speed(6)turtlePath(tab,L)# animation du parcours par la tortue#calling for the mainloop()turtle.mainloop()
Un modèle prédictif ne peut être établi qu’à partir d’une étude prealable de données. Une étude statistique permet de repérer si certains paramètres sont liés entre eux. Alors, si ces données étaient suffisamment nombreuses et précises, il est possible d’établir des lois mathematiques sur ces données. Une manière de représenter ce lien entre paramètres est d’établir une loi de regression linéaire, par exemple.
A partir de nouvelles données, on peut alors, grâce à une simulation, prédire le comportement futur du nouvel objet. A condition que celui-ci fasse partie de la même famille d’objets que ceux qui ont permis d’établir le modèle.
Cliquer sur le lien online tool here au milieu de la page de description.
La page suivante permet de simuler le comportement d’une planete dans son système stellaire. Il suffit de choisir certains paramètres comme par exemple:
la distance de la planète à son étoile
la courbure de sa trajectoire
sa période de revolution
le type d’étoile
sa couverture oceanique
…
Choix des paramètres de la planète
La simulation demarre une fois que l’on clique sur le bouton START.
Simulation du comportement de la planète
Le logiciel utilise alors un modèle prédictif, établi à partir de l’observation de nombreuses autres planètes ou corps celestes, pour déterminer la temperature de surface de l’astre au cours du temps, sa trajectoire, etc…
A tester vous même: faire un test à l’aide du simulateur.
Python unittest
Utilisation du module unittest avec le calcul des nombres premiers
avant de démarrer cette partie, il est recommandé de consulter :
Définition: Un test unitaire est un test réalisé sur une portion du programme, typiquement sur une fonction.
Le module unittest offre des outils de test de code, comme la classe TestCase. Le but est des vérifier que votre code génère des résultats corrects, conformes au attentes.
En pratique: test du calcul de la liste de nombres premiers
Dans le fichier main.py, on mettra les fonctions de test. Ce sera le fichier main que l’on executera.
Créer un deuxieme fichier python, que l’on renommera prime.py. Celui-ci contiendra les fonctions à tester.
modules associés au programme de test
Contenu du fichier prime.py
defprem1(n):"""Renvoie True si l’entier est premier et False sinon"""# script à completerreturnTruedefliste_prime1(N):"""etablit une liste de nombres premiers de 0 a N"""L=[]forjinrange(N+1):ifprem1(j):L.append(j)returnL
Contenu du fichier main.py
importunittestimportprimeclassPrimeTestCase(unittest.TestCase):"""Test pour prime.py"""deftest_prime(self):"""compare avec liste de nombres premiers"""wiki=[2,3,5,7,11,13,17,19,23,29,31,37,41,43,47,53,59,61,67,71,73,79,83,89,97]premiers=prime.liste_prime1(100)self.assertEqual(premiers,wiki)if__name__=='__main__':unittest.main()
Dans le fichier à executer, main.py: On commence par importer le module unittest ainsi que le module prime qui contient les fonctions à tester.
Les noms des classes de test se terminent généralement par TestCase (scenario de test). La classe créée pour le test, PrimeTestCase doit être une classe enfant de unittest.TestCase.
Chaque test à créer est une méthode. Toute méthode dont le nom commence par test_ est exécutée lors du test. La méthode test_prime1 appelle donc la fonction liste_prime du module prime avec la valeur 100, puis vérifie que son résultat est conforme à la liste wiki, grâce à un test d’assertion assertEqual.
Ici, la fonction prem1 n’est pas bien renseignée, et le test échoue. On peut remonter jusqu’à l’erreur dans le Traceback qui est affiché en console.
# extrait du Traceback
Tests failed in PrimeTestCase.test_prime
Ran 1 tests, passed: 0 failed: 1
A vous de jouer
Compléter la fonction prem1 afin que celle-ci calcule bien les nombres premiers entre 0 et 100. Puis lancer le test à l’aide de la classe PrimeTestCase.
Le test se déroule t-il correctement?
Que se passe t-il si on modifie la valeur 100 dans l’instruction premiers = prime.liste_prime1(100) de la méthode test_prime de la classe PrimeTestCase? Conclure
Chiffrer: transformer les caractères d’un texte pour le rendre incompréhensible, sauf pour celui qui possède la clé de chiffrement.
Déchiffrer: transformer le texte chiffré en texte clair à l’aide de la clé de chiffrement
Décrypter: transformer le texte chiffré en texte clair sans posséder la clé.
Cryptologie: science du secret: possède deux branches
cryptographie: étude de l’art du chiffrement
cryptanalyse: analyse des méthodes de chiffrement pour les casser (décrypter)
à quoi sert le chiffrement?
Le chiffrement a pour but de protéger nos données, nos communications, mais aussi de signer nos messages et de s’assurer que l’on communique bien avec la bonne personne:
Authentification: L’authentification est la procédure qui consiste, pour un système informatique, à vérifier l’identité d’une entité (personne, programme, machine).
L’intégrité des données désigne le fait que les données ne soient pas modifiées au cours d’une communication ou de leur stockage.
Ainsi, si vous envoyez un texte chiffré sur un canal non sécurisé, le texte chiffré pourra être intercepté et altéré par un attaquant avant d’atteindre son destinataire. Pour contrôler cette intégrité, on associe au message une valeur de contrôle.
La confidentialité: Le chiffrement permet de protéger la confidentialité de vos données à l’aide d’une clé secrète.
Le chiffrement par décalage, ou chiffre de Caesar
Le chiffre de César fonctionne par décalage des lettres de l’alphabet.
Cet algorithme de chiffrement utilise une fonction périodique pour transformer les rangs de chaque lettre:
a
b
c
d
e
f
g
h
i
j
k
l
m
n
o
p
q
r
s
t
u
v
w
x
y
z
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
Compléter l’algorithme du chiffrement de César. On suppose qu’il existe une clé c correspondant au décalage utilisé. Le message clair est m et le message chiffré est m_chiffre
Décryptage par FORCE BRUTE: Combien y-a-t-il de clés possibles à essayer pour celui qui réalise le décryptage? Conclure.
Un chiffrement par substitution monoalphabetique
Le chiffrement par substitution monoalphabetique: Chaque lettre de l’alphabet est transformée en une nouvelle lettre. Et cette nouvelle lettre est unique (sinon, il y aurait ambigüité, et le déchiffrement ne serait pas possible). Ici, la fonction utilisée pour le chiffrement de César, est un simple décalage:
$$x \rightarrow x + cle$$
Mais il peut y avoir d’autres fonctions plus complexes utilisées. Voire, même aucune fonction, mais une table de correspondance entre lettre en clair et symbole chiffré. La clé aurait alors la longueur de l’alphabet.
Le chiffrement par monosubstitution a été également utilisé par différentes méthodes utilisant une table.
<a href="
Carré de Polybe - le mot « bonjour » est ainsi chiffré par le carré de Polybe :12 34 33 24 34 45 42 - wikipedia
Vous trouvez cette méthode de chiffrement trop simpliste? Regardez alors sa déclinaison avec le chiffrement de Playfair, qui associe une clé à la table de Polybe, et rajoute du pseudo aléatoire dans le chiffrement:
Le code issu du carré de Polybe a été utilisé par les prisonniers, qui transmettaient leur message en tapant sur les murs (Tap code).
Le problème avec ce type de chiffrement monoalphabetique, est qu’il est possible de repérer comment sont transformées certaines lettres à partir de l’analyse fréquentielle du message chiffré.
On peut alors utiliser la frequence des lettres pour dechiffrer et comparer avec la frequence moyenne dans une langue. (200 caracteres suffisent). Il y a aussi tout un tas de statistique, comme les lettres uniques, doubles lettres, finales, etc… C’est un marqueur suffisant pour savoir comment le code est fait.
frequence des lettres en français, calculée sur la lecture de plusieurs ouvrages classiques (10 millions de caracteres)
Ce n’est pas le cas du chiffrement de Playfair, car celui-ci utilise une methode de substitution d’un groupe de lettres: c’est une substitution polyalphabetique.
Une amélioration: Substitution polyalphabétique
L’analyse des fréquences est moins pertinente lorsque le message a été chiffré avec un chiffrement polyalphabétique (qui tend à rendre aléatoire la fréquence des lettres).
Polyalphabetique: Se dit d’un chiffre où un groupe de n lettres est codé par un groupe de n symboles. Le chiffrement Playfair, vu plus haut s’apparente à une substitution polyalphabetique, puisqu’il substitue des digrammes (groupes de 2 lettres) dans le texte d’origine.
L’exemple suivant montre une polysubstitution simple avec une clé de longueur 3 qui va décaler les lettres de l’alphabet :
On définit la clé ‘123’ qui indique que le premier caractère sera décalé d’une position, le second de 2 et le troisième de 3 positions, etc.
Le mot : WIKIPEDIA donne donc dans ce cas XKNJRHEKD.
Mais si on chiffre le mot : AAAAAAAAA cela donnera BCDBCDBCD. La lettre A ne donne pas toujours la même correspondance chiffrée. Mais on peut analyser la périodicité et en déduire la longueur de la clé. La connaissance de la longueur de la clé est essentielle pour pouvoir pratiquer l’analyse frequentielle.
La machine Enigma utilisait ce principe de codage.
La machine utilise des rotors qui sont mis en position selon une clé. L’alphabet est chiffré selon la position initiale de ces rotors. Ceux-ci se décalent lors de l’utilisation. Ce qui modifie l’alphabet chiffré et augmente sérieusement la complexité.
Déchiffrer se fait avec la même machine, à condition d’utiliser la même clé.
Son utilisation la plus célèbre fut celle faite par l’Allemagne nazie, avant et pendant la Seconde Guerre mondiale, la machine étant réputée inviolable selon ses concepteurs.
Le principe de la machine Enigma était connu. Le concepteur savait à l’avance que certains modèles pourraient être volés par les alliés. Ce qui fit son efficacité, c’est le nombre immense de combinaisons possibles pour les réglages initiaux de la machine et le choix de la clef brute du message.
Les cryptanalystes britanniques, dont Alan Turing, purent continuer les travaux du mathématicien polonais Marian Rejewski. Ils furent, dans des circonstances favorables, capables de decrypter les messages Enigma, ce qui donna un avantage certain aux alliés pendant la guerre.
Points communs des chiffrements symétriques
Ces algorithmes fonctionnent selon:
Entrée
repetition n fois de substitutions et permutations. Utilise une clé unique pour chiffrer et dechiffrer.
Sortie
Fondamentaux de la cryptographie moderne
Les principes de Kerckhoff (6 principes, 3 restent aujourd’hui preponderants malgrès la difference de technologie)
Materiellement sûr: Si on a un temps infini, on finira par trouver le code, mais le message n’aura plus d’interêt.
Ce n’est pas l’algorithme qui est secret, ce sont les paramètres. L’algorithme constitue un systeme de confiance. C’est d’ailleurs le même algorithme qui est utilisé par tout le monde et pour tout.
Il faut changer ou modifier la clé toutes les x utilisations.
Les effets recherchés:
Diffusion: propriété où la redondance statistique dans un texte en clair est dissipée dans les statistiques du texte chiffré. (Claude Shannon).
Confusion: correspond à une volonté de rendre la relation entre la clé de chiffrement et le texte chiffré la plus complexe possible (Claude Shannon).
Consequence:L’effet d’avalanche: une modification même minime en entrée va entrainer de grandes modifications en sortie.
Chiffrements asymétriques
Pour le chiffrement symétrique, le seul secret, c’est la clé de chiffrement. Cette clé doit avoir, pour des raisons pratiques, une longueur raisonnable (64, 128, 256 bits). Ce chiffrement permet de communiquer de manière confidentielle, ou de préserver la confidentialité de nos données sur un disque dur. Le problème avec le seul chiffrement symétrique, c’est qu’il ne permet pas de repondre aux besoins d’authentification (reconnaitre l’identité) et d’authenticité (le message n’a pas été modifié).
Pour comprendre ces termes, on utilise le scenario suivant. Alice et Bob sont 2 personnes qui veulent echanger des messages de manière sécurisée. Une 3e personne, appelée Trudy joue le rôle d’un attaquant.
Le trio Alice - Bob - Trudy
Le chiffrement asymétrique utilise plusieurs clés, une pour le chiffrement, et une autre pour le dechiffrement. Il repose sur des propriétés mathématiques de l’arithmetique modulaire. (voir principe du chiffrement RSA)
Principe du chiffrement RSA
Confidentialité
Il doit y avoir 2 clés. L’une de ces clés doit rester secrête, et conservée par l’expediteur du message: c’est la clé privée. L’autre clé utile pour le chiffrement et le dechiffrement est partagée: elle est dite publique. On peut indifféremment chiffrer avec la clé publique et déchiffrer avec celle privée, ou l’inverse.
Ainsi, comme la clé de Bob est publique, Alice peut utiliser cette clé pour chiffrer le message qu’elle veut lui envoyer, un peu comme si elle mettait le message dans un coffre (celui de Bob). Et Bob, qui possède la clé privée correspondante (la clé de son coffre) peut alors déchiffrer le message d’Alice.
Chiffrement asymetrique
Authentification
On peut utiliser cet algorithme pour authentifier l’auteur du message, et réaliser une signature numérique.
Imaginons que Bob utilise sa clé privée pour chiffrer un message M. Il l’envoie à Alice, qui, en utilisant la clé publique de Bob, pourra le déchiffrer. Elle pourra ainsi s’assurer que Bob en est bien à l’origine et que son contenu n’a pas été modifié.
En effet, comme il est le seul à posséder la clé privée, ce message M vient bien de Bob.
Compléter la situation où Bob envoie un message de type Bonjour à Alice, en utilisant sa clé privée:
Bonjour Alice - via chiffrement asymetrique
Le point faible de cet échange vient de la distribution de la clé publique entre Bob et Alice.
Cet échange n’est réellement sécurisé qu’à la condition que la clé publique de Bob, vienne bien de Bob. Et que personne ne se soit introduit dans la discussion pour substituer la clé publique de Bob par la sienne (attaque de l’homme du milieu).
Compléter la situation suivante où Eve réalise une attaque dite de l’homme du milieu. Elle envoie au préalable sa propre clé publique à Alice et Bob. Puis elle se fait passer pour chacun des 2 lors de la discussion.
Bonjour Alice, bonjour Bob - Eve
Pour s’authentifier, Bob doit d’abord envoyer à Alice un certificat, qui contient sa clé publique mais aussi d’autres informations qui permettent de verifier la validité de ce certificat, en particulier l’emetteur: le nom de l’autorité de certification, une infrastructure à clé publique (PKI) qui a validé l’identité de Bob.
Certificats: Les navigateurs permettent d’ouvrir les pages des sites qui ont pu être authentifiés. Pour faire ceci, les navigateurs intègrent un certain nombre de certificats reconnus. Pour les autres, ils utilisent une chaine de certification: les navigateurs font confiance à certaines autorités de certification, qui ont au préalable, certifié leurs clients (possesseurs de sites web).
Si la chaine de confiance est rompue, votre navigateur affiche cette image qui va certainement vous dissuader de poursuivre votre navigation:
certificat non reconnu
En pratique, le certificat est un ensemble d’informations sur le propriétaire du domaine, la durée de validité, l’algorithme utilisé pour l’authentification, la clé publique, et surtout l’emetteur. Lorsqu’Alice reçoit le certificat que lui envoie Bob, elle consulte l’emetteur du certificat pour verifier qu’il s’agit bien du bon certificat, que celui-ci appartient bien à Bob.
procedure d'echange de certificat
Principe d’une communication securisée HTTPS
Lors d’une communication HTTPS: les objectifs d’authentification, authenticité et de confidentialité sont remplis. Lors du protocole de communication, les chiffrements asymétriques et symétriques sont tous 2 utilisés:
Que Se Passe-t-il Entre un Navigateur Web (client) et un Serveur ?
le client demande au serveur que celui-ci s’authentifie (1)
Le serveur envoie au navigateur une copie de son certificat SSL (2)
Le navigateur vérifie s’il fait confiance à ce certificat SSL. Si oui,le client envoie de manière sécurisée une clé de session qui servira pour la communication (3). L’envoie de la clé se fait à l’aide du chiffrement asymétrique (RSA). Le client utilise la clé publique du serveur pour cet envoi.
Cette clé sera utilisée pour des chiffrements symétriques entre le client et le serveur (4).
Signature numérique: Lorsqu’on utilise sa propre clé privée pour envoyer un message, et qu’une autorité de certification peut garantir l’origine de cette clé privée, alors ce message envoyé a valeur de signature numérique. Il permet d’authentifier l’emetteur du message.
Exercices
Substitution monoalphabétique: Code de César
Question 1: Quelle clé a été utilisée pour chiffer ce texte (avec l’algorithme de César)?
jyfwavnyhwopl hwwspxbll
Question 2: Décrypter ce message.
Question 3: Proposer un programme en python qui chiffre un message clair m en un message codé selon la clé numérique c.
Aide:
La fonction ord('x') retourne un entier correspondant à la position d’un caractère dans la table ascii.
Par exemple, ord('A') retourne 65, ord('B') retourne 66,…
La fonction chr(N) retourne le caractère de rang N: chr(65) retourne ‘A’.
Substitution polyalphabétique: Chiffrement de Playfair
A partir des explications données dans la video:
Question 1: Construisez la matrice pour l’algorithme de Playfair avec la clé estienne.
Question 2: Chiffrer le message: COUPERLETRANSMETTEUR.
Question 3: S’agit-il d’une méthode utilisant la substitution monoalphabetique, ou polyalphabetique?
Question 4: Est-ce qu’avec cette méthode, le decryptage peut être facilité par l’analyse fréquentielle?
Frequences des lettres dans un texte
La fonction suivante retourne une liste de 26 valeurs de type float, donnant dans l’ordre de l’alphabet, la frequence pour chaque lettre dans un texte:
deffreq(m):frequences=[0]*26n=len(m)forcinm:...
Question 1: Compléter le script de la fonction freq.
Question 2: L’un des 2 a été chiffré avec un algorithme de substitution mon-alphabetique, et l’autre, poly-alphabétique. Lequel est mono-alphabétique?
Chiffrement symetrique par la fonction XOR
Cet exercice est inspiré du TP cryptographie du site de hmalherbe.fe - NSI
La fonction XOR est la fonction du OU EXCLUSIF.
Question 1: Donner la table de vérité de la fonction XOR
Question 2: Programmer la fonction xor en python qui retourne le resultat de XOR appliqué aux 2 paramètres a et b.
Exemple:
>>> xor(0,1)
>>> 1
On utilisera pour cet exercice les fonctions suivantes, qui permettent de transformer un texte en binaire, à partir du code ascii des lettres:
deftext2bin(texte):""" convertit une chaine de caracteres en binaire
param:
texte: str, une chaine de caracteres
return:
bin: str, une sequence de 8 bits par caracteres
chaque sequence de 8 bits est la valeur du code ascii du caractere
convertie en binaire (sur un octet)
exemple:
>>> text2bin('HELLO')
>>> '0100100001000101010011000100110001001111'
"""bin=''forlintexte:bits=f'{ord(l):b}'# f est une fonction de formatage et convertit# une valeur decimale ord(l) en binaire# ord(l) donne la valeur numerique correspondant au caractere ascii loct=octet(bits)bin+=octreturnbindefoctet(bits):""" rajoute les 0 au nombre binaire pour mettre en format de 8 bits
"""byte=str(bits)foriinrange(8-len(bits)):byte='0'+bytereturnbyte
Question 3: programmer toutes ces fonctions dans un fichier python (ou un notebook). Tester en particulier la fonction text2bin sur un texte relativement court (2 caractères). Recopier le résultat obtenu.
La fonction suivante transforme une séquence de chiffres binaires en une valeur décimale:
defbin2dec(oct):# oct est un str de 8 caracteresn=0foriinrange(len(oct)):n+=int(oct[-i-1])*2**ireturnn
Exemple:
>>> bin2dec('001001')
>>> 9
Question 4: Utiliser cette fonction pour écrire le script de bin2text, la fonction inverse de text2bin, qui, pour une sequence binaire donnée, de longueur multiple de 8 bits, retourne la chaine de caracteres correspondants.
Le XOR (OU exclusif) est très utilisé dans les protocoles de chiffrement symétrique. En effet, c’est une opération qui est sa propre réciproque, ce qui n’est pas le cas du ET ni du OU.
On souhaite chiffrer un message (par exemple une chaîne de caractères) à l’aide d’une clé binaire. Seuls des caractères ASCII sont utilisés.
Question 5: Ecrire le script de cette fonction, que l’on appelera chiffre_xor. Cette fonction prend 2 paramètres: la séquence de bits à chiffrer, ainsi que la clé de chiffrement. Cette clé est de dimension inférieure ou égale au premier paramètre. Il faudra l’appliquer de manière périodique aux bits de la séquence à chiffrer (voir cours sur le chiffrement poly-alphabetique).
Question 6: Utiliser les fonctions du programme pour:
convertir un message secret en une sequence binaire
chiffrer cette sequence binaire avec l’algorithme XOR, en utilisant la clé 10101