Archives de catégorie : NSI

Structures de données : les graphes

copie de l’article :

https://info-mounier.fr/terminale_nsi/structures_donnees/graphes

merci

Table des matières

  • Introduction
  • Définitions et vocabulaire
    • Vocabulaire des graphes non orientés
    • Vocabulaire des graphes orientés
    • Graphes valués
  • Représentations d’un graphe
    • Représentation par matrice d’adjacence
    • Représentation par listes des successeurs
    • Efficacité des représentations
  • Implémentations
    • Par une matrice d’adjacence
    • Par une liste de successeurs
    • Passage d’une représentation à l’autre
  • Bilan

Introduction

Les graphes sont une structure de données très riche permettant de modéliser des situations variées de relations entre un ensemble d’entités :

  • entre les ordinateurs du réseau internet ;

réseau Internet

Source : Wikipedia, Mro, licence CC BY-SA 3.0

  • entre des personnes sur un réseau social ;

réseau Internet

Source : Pixabay

  • entre les villes dans un réseau routier ou de distribution ;

réseau Internet

Source : Wikipedia, HB, licence CC BY-SA 3.0

  • entre les atomes d’une molécule ;

réseau Internet

Source : Wikipedia, William Crochot, licence CC BY-SA 4.0

  • entre les ressources du Web (les relations sont les liens hypertextes) ;
  • entre deux situations dans un jeu ;
  • etc.

Les relations peuvent être orientées ou non.

Définitions et vocabulaire

Un graphe est constitué d’un ensemble de sommets et dans le cas orienté d’un ensemble d’arcs reliant chacun un sommet à un autre, dans le cas non orienté d’un ensemble d’arêtes entre deux sommets.

Mathématiquement, un graphe G est donc un couple formé de deux ensembles : X = { x 1 , x 2 , … , x n }

dont les éléments sont appelés les sommets et un ensemble A = { a 1 , a 2 , … , a m } dont les éléments sont appelés les arêtes dans le cas non orienté ou les arcs dans le cas orienté. Une arête (ou un arc) a i

est un couple de deux sommets, par exemple : a i = ( x 2 , x 5 )

symbolise le lien (arête ou arc) entre les sommets x 2 et x 5

. On peut noter G = ( X , A )

.

Vocabulaire des graphes non orientés

Dans le cas des graphes non orientés, les relations entre deux sommets se font dans les deux sens. On appelle ses relations des arêtes (edges en anglais), et on a les définitions suivantes.

  • Sommets adjacents : deux sommets sont adjacents s’ils sont reliés entre eux par une arête. On dit que l’arête est incidente aux deux sommets.
  • Voisins d’un sommet x : ce sont tous les sommets reliés à x par une arête .
  • Degré d’un sommet x : nombre d’arêtes incidentes au sommet , on le note d ( x ).
  • Chaîne : séquence ordonnée d’arêtes telle que chaque arête a une extrémité en commun avec l’arête suivante.
  • Cycle : dans un graphe non orienté, un cycle est une suite d’arêtes consécutives (chaîne) dont les deux sommets extrémités sont identiques.
  • Boucle : il peut exister des arêtes entre un sommet x et lui-même. Elles sont appelés boucles.

Exemple

graphe non orienté
  • Ce graphe non orienté est donné par :
    • un ensemble de sommets : { A , B , C , D , E , F , G }
    • un ensemble d’arêtes : { ( A , B ) , ( A , F ) , ( A , G ) , ( B , C ) , ( B , F ) , … }

  • Les sommets A et B sont adjacents mais B et D ne le sont pas.
  • Les voisins du sommet A sont B, F et G .
  • Le degré du sommet A est égal à 3 (d ( A ) = 3).
  • A , B , C , D est une chaîne, A , B , F aussi.
  • A , F , G , A est un cycle.
  • Il y a une boucle ( E , E ) . Le degré de E est égal à 4.

Vocabulaire des graphes orientés

Dans le cas des graphes orientés, les arêtes ont un sens et elles sont appelées arcs. Par exemple, l’arête a = ( x , y ) indique qu’il y a un arc d’origine x et d’extrémité finale y. De plus, on a les définitions suivantes.

  • Successeurs et prédécesseurs d’un sommet x : dans un graphe orienté on ne parle plus de voisins d’un sommet mais de ses successeurs et de ses prédécesseurs : le successeurs de x sont tous les sommets tels qu’il existe un arc ( x , y ) (de x vers y ) et les prédécesseurs de x sont tous les sommets w tels qu’il existe un arc ( w , x ) (de w vers x).
  • Chemin : séquence ordonnée d’arcs consécutifs (on parlait de chaîne dans un graphe non orienté).
  • Circuit : dans un graphe orienté, un circuit est une suite d’arcs consécutifs (chemin) dont les deux sommets extrémités sont identiques.
  • Degré d’un sommet x : cette notion existe aussi dans le cas des graphes orientés. On distingue le degré entrant d’un sommet x (noté d − ( x )= nombre de prédécesseurs de x ) et le degré sortant d’un sommet x (noté d + ( x ) = nombre de successeurs de x ). Le degré d’un sommet x vaut d ( x ) = d + ( x ) + d − ( x )
  • Boucle : ce sont les arcs entre un sommet et lui-même.

Exemple

graphe non orienté
  • Ce graphe orienté est donné par :
    • un ensemble de sommets : { A , B , C , D , E , F , G },
    • un ensemble d’arcs : { ( A , B ) , ( A , F ) , ( B , C ) , ( C , F ) , ( C , D ) , … }
  • Les successeurs de A sont les sommets B et F , le seul prédécesseur de A est G . Le degré du sommet A est égal à 3 : d ( A ) = d + ( A ) + d − ( A ) = 2 + 1 = 3 .
  • A , B , C , D est un chemin mais A , B , F n’en est pas un car il n’y a pas d’arc ( B , F ) (de B vers F ).
  • A , F , G , A est un circuit.
  • Il n’y a pas de boucle ici.

Graphes valués

Certains graphes (orientés ou non) sont dits valués : on ajoute un coût (ou valuation, ou poids) à chaque arête/arc. Dans le cas d’un graphe représentant un réseau routier, le coût sur chaque arête pourrait, par exemple, être la distance entre deux villes.

graphe valué

Représentations d’un graphe

Représentation par matrice d’adjacence

Une matrice M est un tableau de nombres, qui peut être représenté en machine par un tableau de tableaux (ou une liste de listes) noté matrice. Chaque nombre de cette matrice est repéré par son numéro de ligne i et son numéro de colonne j. On note ce nombre M i , j et on peut y accéder par l’instruction matrice[i][j].

Un graphe à sommets peut être représentée par une matrice d’adjacence de taille n x n , où la valeur du coefficient d’indice i , j

dépend de l’existence d’une arête ou d’un arc reliant les sommets i et j.

Exemple (graphe non orienté) : Si les sommets A , B , C , …du graphe

graphe non orienté

sont respectivement numérotés 0, 1 , 2, etc. alors sa matrice d’adjacence est

Par exemple, le sommet C correspond à la troisième ligne. Celle-ci contient dans cet ordre les nombres 0, 1, 0, 1, 0, 1, 0 donc cela signifie qu’il y a des arêtes ( C , B ) , ( C , D ) et ( C , F ) (les 1) mais pas entre C et les sommets A, C, E et G (les 0).

Cette matrice peut être mémorisée en machine par le tableau de tableaux suivant.

matrice = [
    [0, 1, 0, 0, 0, 1, 1],
    [1, 0, 1, 0, 0, 1, 0],
    [0, 1, 0, 1, 0, 1, 0],
    [0, 0, 1, 0, 1, 0, 0],
    [0, 0, 0, 1, 1, 1, 0],
    [1, 1, 1, 0, 1, 0, 1],
    [1, 0, 0, 0, 0, 1, 0]
]

Dans le cas d’un graphe non orienté, la matrice d’adjacence est nécessairement symétrique par rapport à sa diagonale : on a M i , j = M j , i

.

Exemple (graphe orienté) :

C’est le même principe en faisant attention au sens des arcs : M i , j = 1 s’il y a un arc d’origine i et d’extrémité j et M i , j = 0 sinon. Ainsi, le graphe

graphe non orienté

a pour matrice d’adjacence

Par exemple, le sommet C correspond à la troisième ligne. Celle-ci contient dans cet ordre les nombres 0, 0, 0, 1, 0, 1, 0 donc cela signifie qu’il y a des arcs (C,D) et (C,F) (les 1) mais pas entre C et les autres sommets (les 0).

Comme les arcs ont un sens, la matrice d’adjacence d’un graphe orienté n’est généralement pas symétrique.

Représentation par listes des successeurs

Une autre façon de représenter un graphe est d’associer à chaque sommet la liste des sommets auxquels il est relié. Dans le cas d’un graphe orienté, on parle de liste de successeurs, alors que dans le cas d’un graphe non orienté on parle de liste de voisins.

Une façon simple et efficace est d’utiliser un dictionnaire où chaque sommet est associé à la liste de ses successeurs/voisins.

Exemples :

  • Le graphe non orienté graphe non orienté peut être représenté par le dictionnaire suivant, où les clés sont les sommets et les valeurs sont les listes de voisins.
dico1 = {
    "A": ["B", "F", "G"],
    "B": ["A", "C", "F"],
    "C": ["B", "D", "F"],
    "D": ["C", "E"],
    "E": ["D", "E", "F"],
    "F": ["A", "B", "C", "E", "G"],
    "G": ["A", "F"]
}

  • Le graphe orienté graphe non orienté peut être représenté par le dictionnaire suivant, où les clés sont les sommets et les valeurs sont les listes de successeurs.
dico2 = {
    "A": ["B", "F"],
    "B": ["C"],
    "C": ["D", "F"],
    "D": ["C"],
    "E": ["D"],
    "F": ["B", "E", "G"],
    "G": ["A"]
}

Efficacité des représentations

La matrice d’adjacence est simple à mettre en œuvre mais nécessite un espace mémoire proportionnel à n x n (où n est le nombre de sommets). Ainsi, un graphe de 1000 sommets nécessite une matrice d’un million de nombres même si le graphe contient peu d’arêtes/arcs. Pour le même graphe contenant peu d’arêtes/arcs, le dictionnaire ne mémoriserait pour chaque sommet que les voisins/successeurs (les 1) sans avoir à mémoriser les autres (les 0). En revanche, pour un graphe contenant beaucoup d’arêtes/arcs, la dictionnaire occuperait plus d’espace mémoire que la matrice d’adjacence.

Cela implique en outre que l’accès aux voisins/successeurs d’un sommet est plus rapide avec le dictionnaire car il n’est pas nécessaire de parcourir toute la ligne de la matrice ( n valeurs) alors même que celle-ci peut ne contenir que très peu de 1.

De plus, l’utilisation d’un dictionnaire permet de nommer les sommets sans ambiguité et ne les limite pas à des entiers comme c’est le cas pour la matrice d’adjacence (même si on peut associer chacun de ces entiers au sommet correspondant, ce que nous avons fait précédemment).

Enfin, au lieu d’utiliser le type liste (list de Python ici) pour mémoriser les voisins/successeurs, on peut avantageusement utiliser le type ensemble (type prédéfini set de Python) qui est une structure de données permettant un accès plus efficace aux éléments (l’implémentation se fait par des tables de hachage, hors programme de NSI).

✏️ A faire : tous les exercices du notebook d’activités !

Implémentations

La fin de ce cours résume une partie de ce qui a été fait en exercices, notamment deux implémentations du type GrapheNonOriente défini par l’interface suivante :

  • faire_graphe(sommets) pour construire un graphe (sans les arêtes) à partir de la liste sommets de ses sommets.
  • ajouter_arete(G, x, y) pour ajouter une arête entre les sommets x et y du graphe G.
  • sommets(G) pour accéder à la liste des sommets du graphe G.
  • voisins(G, x) pour accéder à la liste des voisins du sommet x du graphe G.

La première implémentation se fait par une classe GrapheNoMa s’appuyant sur la représentation par une matrice d’adjacence et la seconde par une classe GrapheNoLs s’appuyant sur les listes de successeurs (qui sont les voisins dans le cas d’un graphe non orienté).

On termine en présentant comment passer d’une représentation à l’autre.

Par une matrice d’adjacence

Voici la classe GrapheNoMa s’appuyant sur une matrice d’adjacence.

class GrapheNoMa:
    def __init__ (self, sommets):
        self.som = sommets
        self.dimension = len(sommets)
        self.adjacence = [[0 for i in range(self.dimension)] for j in range(self.dimension)]

    def ajouter_arete(self, x, y):
        i = self.som.index(x)
        j = self.som.index(y)
        self.adjacence[i][j] = 1
        self.adjacence[j][i] = 1

    def sommets(self):
        return self.som

    def voisins(self, x):
        i = self.som.index(x)
        return [self.som[j] for j in range(self.dimension) if self.adjacence[i][j] == 1]

Par une liste de successeurs

Voici la classe GrapheNoLs s’appuyant sur un dictionnaire contenant les listes de successeurs de chaque sommet.

class GrapheNoLs:
    def __init__ (self, sommets):
        self.som = sommets
        self.dic = {sommet: [] for sommet in self.som} # création par compréhension

    def ajouter_arete(self, x, y):
        if y not in self.dic[x]:
            self.dic[x].append(y)
        if x not in self.dic[y]:
            self.dic[y].append(x)

    def sommets(self):
        return self.som

    def voisins(self, x):
        return self.dic[x]

Python

On peut alors créer des graphes comme objets de ces deux classes et leur ajouter des arrêtes.

>>> g1 = GrapheNoMa(["a", "b", "c", "d"])  # implémentation par matrice d'adjacence
>>> g1.ajouter_arete("a", "b")
>>> g1.ajouter_arete("a", "c")
>>> g1.ajouter_arete("c", "d")

Python

>>> g2 = GrapheNoLs(["a", "b", "c", "d"])  # implémentation par liste de successeurs
>>> g2.ajouter_arete("a", "b")
>>> g2.ajouter_arete("a", "c")
>>> g2.ajouter_arete("c", "d")

On peut accéder aux graphes à travers les fonctions de l’interface du type abstrait de manière totalement identique.

>>> g1.sommets()
['a', 'b', 'c', 'd']
>>> g1.voisins("c")
['a', 'd']

>>> g2.sommets()
['a', 'b', 'c', 'd']
>>> g2.voisins("c")
['a', 'd']

En Python, un utilisateur malin pourra observer la façon dont sont mémorisées les graphes dans les deux cas :

>>> g1.adjacence
[[0, 1, 1, 0], [1, 0, 0, 0], [1, 0, 0, 1], [0, 0, 1, 0]]
>>> g2.dic
{'a': ['b', 'c'], 'b': ['a'], 'c': ['a', 'd'], 'd': ['c']}

Mais nous avons vu qu’il est possible de palier à ce problème en définissant une méthode de représentation identique dans chacune des deux classes pour masquer cette différence d’implémentation, qui importe peu à l’utilisateur de la classe.

Passage d’une représentation à l’autre

Les deux implémentations sont totalement équivalentes et on peut passer de l’une à l’autre simplement en énumérant les sommets et les voisins depuis une représentation tout en construisant l’autre représentation.

Par exemple, la fonction suivante permet de passer d’une matrice d’adjacence à une liste de successeurs (la fonction de traduction réciproque est similaire).

def ma_to_ls(gma):
    gls = GrapheNoLs(gma.sommets())
    for x in gma.sommets():
        for y in gma.voisins(x):
            gls.ajouter_arete(x,y)
    return gls

>>> g3 = ma_to_ls(g1)
>>> g1.adjacence  # représentation de départ
[[0, 1, 1, 0], [1, 0, 0, 0], [1, 0, 0, 1], [0, 0, 1, 0]]
>>> g3.dic  # traduction
{'a': ['b', 'c'], 'b': ['a'], 'c': ['a', 'd'], 'd': ['c']}

On peut implémenter le type abstrait GrapheOriente de façon quasiment similaire (fait en exercices).

Bilan

  • Le graphe est une structure de données permettant de modéliser de nombreuses situations de la vie courante.
  • Il est définit par un ensemble de sommets et de liaisons. Ces liaisons peuvent être orientées ou non et on les appelle alors respectivement des arcs ou des arêtes.
  • On peut représenter en machine un graphe par une matrice d’adjacence ou par un dictionnaire contenant les listes de successeurs (de chaque sommet).
  • La programmation par des classes de deux implémentations d’un graphe non orienté (resp. orienté) a prouvé que celles-ci étaient indépendantes de l’interface du type abstrait GrapheNonOriente (resp. GrapheOriente) et qu’elles sont équivalentes, on peut notamment passer de l’une à l’autre facilement.
  • Nous verrons dans un prochaine chapitre différents algorithmes sur les graphes (parcours en profondeur d’abord, en largeur d’abord, repérer des cycles, recherche de chemin dans un graphe).

Références :

  • Equipe pédagoqique DIU EIL, Université de Nantes.

Germain BECKER, Lycée Mounier, ANGERS

Installation linux

Lire l’article sur Clubic.

https://www.clubic.com/telecharger/actus-logiciels/article-842846-1-10-distributions-gnu-linux-preferees-dire-adieu-windows-10.html

Choisir une version de linux,

par exemple MINT:

https://www.linuxmint.com/index.php

Suivre les instructions de téléchargement, d’installation.

Installer le disque dur sur le pc , faire une fiche de la composition de l’ordinateur, Mémoire, Disque dur, Processeur…..

Pensez à préciser la version de linux que vous avez installé, avec les différents nom d’utilisateur et mot de passe.

1- Les variables

Merci à David Roche pour son travail que vous pouvez retrouver sur son site.

Le langage que nous allons utiliser en NSI est Python, pour écrire nos programmes nous devons utiliser un éditeur (IDE , Integrated Development Environment).

Il en existe une multitude, nous utiliserons Thonny. Vous pouvez l’installer chez vous en suivant les indications sur le site thonny.org.

Prise en main de Thonny

Thonny lancé, à l’écran vous devriez avoir ceci:

Thonny possède plusieurs fenêtres. Pour les faire apparaitre ou disparaitre, cliquer dans le menu Affichage et cochez celles qui vous intéressent. Nous en utiliserons 3 en particulier, la fenêtre Éditeur (qui permet de saisir les lignes de programme), la fenêtre Console (interpréteur interactif qui permet l’interaction entre le programme et l’utilisateur) et la fenêtre Variables (qui affiche l’état des variables).

À faire vous-même 1

Dans la fenêtre « Éditeur« , saisir le programme suivant :

print("hello world !")

puis lancer votre programme (en appuyant sur F5 ou en cliquant sur la flèche blanche sur fond vert) (avant la première exécution on vous demandera d’enregistrer votre programme, faites attention ou vous stockez vos fichiers…)

le message hello world ! doit apparaître dans la console:

Notion de variable

Définition du mot ordinateur d’après « Le Petit Larousse » :

« Machine automatique de traitement de l’information, obéissant à des programmes formés par des suites d’opérations arithmétiques et logiques. »

Qui dit « traitement de l’information », dit donc données à manipuler. Un programme « passe » donc son temps à traiter des données. Pour pouvoir traiter ces données, l’ordinateur doit les ranger dans sa mémoire (RAM – Random Access Memory). La RAM se compose de cases dans lesquelles nous allons ranger ces données (une donnée dans une case). Chaque case a une adresse (ce qui permet au processeur de savoir où sont rangées les données).

Alors, qu’est-ce qu’une variable ?

Eh bien, c’est une petite information (une donnée) temporaire que l’on stocke dans une case de la RAM. On dit qu’elle est « variable », car c’est une valeur qui peut changer pendant le déroulement du programme.

Une variable est constituée de 2 choses :

  • Elle a une valeur : c’est la donnée qu’elle « stocke » (par exemple le nombre entier 5)
  • Elle a un nom : c’est une étiquette qui permet de la reconnaître. Nous n’aurons pas à retenir l’adresse de mémoire, nous allons juste indiquer des noms de variables à la place.
i = 12			

Grâce à cette ligne, nous avons défini une variable qui porte le nom i et qui « contient » le nombre entier 12. Plus précisément, nous dirons que la variable i référence le nombre entier 12.

À faire vous-même 2

Dans la partie « éditeur » de Thonny, saisir le code suivant :

point_de_vie = 15			

Après avoir exécuté le programme en cliquant sur Executer le script courant, il est possible de connaître la valeur référencée par une variable en utilisant la partie « console » de Thonny.

Dans le cas qui nous intéresse ici, taper point_de_vie dans la console

Après avoir appuyé sur la touche « Entrée« , vous devriez voir la valeur référencée par la variable point_de_vie s’afficher dans la console.

N.B. : Dans la suite, la procédure sera toujours la même :

  • Vous utiliserez la partie « éditeur » pour saisir votre programme
  • vous utiliserez la partie « console » pour afficher la valeur référencée par une variable

À faire vous-même 3

Écrire un programme dans lequel on attribue la valeur 12 à la variable point_de_force. La valeur référencée par la variable point_de_force devra ensuite être affichée dans la console.


Nous venons de voir qu’une variable peut référencer un nombre entier, mais elle peut aussi référencer un nombre à virgule :

i = 5.2			

Prenez bien garde, nous utilisons un point à la place d’une virgule (convention anglo-saxonne).

Une variable peut donc référencer plusieurs types d’entités (pour l’instant nous n’en avons vu que deux, mais nous en verrons d’autres plus loin) : les nombres entiers (« integer » en anglais, abrégé en « int« ) et les nombres à virgule (« float » en anglais). Il est possible de connaitre le type de l’entité référencé par une variable à l’aide de l’instruction « type« .

À faire vous-même 4

Tester le programme suivant :

a = 5.2
b = 12			

taper type(a) puis type(b) dans la console

Comme vous pouvez le constater, le type de la grandeur référencée par la variable a et le type de la grandeur référencée par la variable b s’affichent dans la console


Un peu de calculs

Un ordinateur est bien évidemment capable d’effectuer des opérations mathématiques (arithmétiques).

Les signes utilisés sont classiques : +, – , * (multiplication), / (division), // (division euclidienne) ou encore % (modulo : reste d’une division euclidienne).

Il est tout à fait possible d’effectuer des opérations directement avec des nombres, mais il est aussi possible d’utiliser des variables.

À faire vous-même 5

Essayer d’écrire un programme qui additionnera le contenu de 2 variables (nom des variables : nombre_1 et nombre_2). Le résultat de cette opération devra être référencé par une troisième variable nommée resultat (attention pas d’accent dans les noms de variable). Tester votre programme en utilisant la console pour vérifier la valeur référencée par la variable résultat.


À faire vous-même 6

D’après vous, que fait ce programme ?

nombre = 11
nombre = nombre + 1			

Vérifier votre réponse en exécutant le programme (utilisation dans console pour déterminer la valeur référencée par la variable nombre à la fin du programme)


Détaillons ce qui se passe dans le « À faire vous-même 6« :

  • nous créons une variable nombre qui référence l’entier 11
  • nous affichons à l’écran la valeur référencée par nombre (c’est-à-dire 11)

La suite est un peu plus complexe, mais très importante à comprendre. Il va falloir lire la ligne  » nombre = nombre + 1″ de droite à gauche, décortiquons cette ligne :

  •  » nombre + 1″ : nous prenons la valeur actuelle de nombre (c’est-à-dire 11) et nous ajoutons 1 à 11, à droite de l’égalité nous avons donc maintenant la valeur 12
  • nous attribuons la valeur qui vient d’être calculée à la variable nombre
  • nous affichons à l’écran la nouvelle valeur référencée par nombre

Ce raisonnement peut être généralisé pour éviter des erreurs parfois difficiles à corriger : dans une égalité, commencer toujours par évaluer l’expression se trouvant à droite du signe égal.

Exposant, racine carrée, fonctions trigonométriques

Il est aussi possible d’effectuer des calculs plus complexes en utilisant par exemple des exposants, des racines carrées, des fonctions trigonométriques…

Pour utiliser ces fonctions mathématiques plus avancées, il est nécessaire d’ajouter une ligne au début de votre programme :

import math			

Cette ligne permet d’importer (et donc d’utiliser) le module « math » (ce module contient toutes les fonctions mathématiques « classiques »).

Voici quelques exemples :

  • math.pow(x,a) permet de calculer x à la puissance a
  • math.cos(x) permet de calculer le cosinus de l’angle x (l’angle x doit être en radian) (nous avons la même chose pour le sinus ou la tangente)
  • math.sqrt(x) permet de calculer la racine carrée de x

Si vous avez besoin d’autres fonctions mathématiques, consulter la documentation de Python : https://docs.python.org/3/library/math.html

À faire vous-même 7

Quelles sont les valeurs référencées par les variables d, e, f, g, h et i après l’exécution du programme suivant :

import math
a = 5
b = 16
c = 3.14 / 2
d = b / a
e = b // a
f = b % a
g = math.pow(a,2)
h = math.sqrt(b)
i = math.sin(c)			

Vérifiez vos réponses à l’aide de la console


À noter qu’il est tout à fait possible de « mélanger » des nombres entiers et des nombres à virgules (« 3.14 / 2 ») dans une opération.

À faire vous-même 8

Écrire un programme permettant de répondre à la question suivante : « Quel est le type du résultat d’une addition d’un integer et d’un float ? »


Chaînes de caractères

Les variables peuvent aussi référencer des suites de caractères, que l’on appelle « chaîne de caractères ».

À faire vous-même 9

Tester le code suivant :

ma_chaine = "Bonjour le monde !"			

Vérifiez que la variable ma_chaine référence la chaîne de caractères « Bonjour le monde ! »


Le signe + et les chaînes de caractères

L’utilisation du signe + ne se limite pas à l’addition. Il est aussi utilisé pour la concaténation.

D’après Wikipédia :

« Le terme concaténation (substantif féminin), du latin cum («avec») et catena(«chaîne, liaison»), désigne l’action de mettre bout à bout au moins deux chaînes. »

Comme vous avez pu le deviner en lisant la définition ci-dessus, la concaténation va concerner les chaînes de caractères.

À faire vous-même 10

Quelle est la chaîne de caractère référencée par la variable mon_expression après l’exécution du programme ci-dessous ? Validez votre réponse en testant ce programme.

a = "Hello"
b = "World"
mon_expression = a + b			

Chaînes de caractères et variables

Il est aussi possible de concaténer une chaîne de caractères et une ou plusieurs variables :

À faire vous-même 11

Tester le code suivant :

ma_chaine_1 = "Bonjour "
ma_chaine_2 = "le "
res = ma_chaine_1 + ma_chaine_2 + "monde!"		

Les 2 variables ma_chaine_1 et ma_chaine_2 référencent 2 chaînes de caractères, nous avons donc bien ici une concaténation.

Mais que se passe-t-il si la variable référence un nombre (entier ou flottant) ?

À faire vous-même 12

Tester le code suivant :


mon_nombre = 5
res = "Nombre de personnes : " + mon_nombre

Comme vous pouvez le constater, nous avons droit à une erreur. En effet, il n’est pas possible de concaténer une chaîne de caractères et un nombre.

Python nous offre 2 solutions :

  • l’utilisation de la méthode « str »
  • l’utilisation des « fstring »

La méthode (nous verrons plus loin la notion de méthode) « str » permet de transformer un nombre en chaîne de caractères (si la transformation n’est pas possible, nous aurons une erreur)

À faire vous-même 13

Tester le code suivant :

mon_nombre = 5
mon_nombre = str(mon_nombre)		

Quel est le type de la valeur référencée par la variable mon_nombre après l’exécution du programme ci-dessus ?


À faire vous-même 14

Tester le code suivant :

mon_nombre = 5
res = "Nombre de personnes : "  + str(mon_nombre)

Tout fonctionne, car maintenant nous avons bien une concaténation entre 2 chaînes de caractères.


Les « fstring » (nouveauté de Python 3.5), permettent de résoudre ce problème de combinaison variable-chaîne de caractères.

À faire vous-même 15

Tester le code suivant :

mon_nombre = 5
res = f"Nombre de personnes : {mon_nombre}"	

Notez la présence du « f » juste avant le guillemet et des accolades qui encadrent le nom de la variable. Il est possible, dans une même chaîne de caractères d’avoir plusieurs noms de variable.

Suite : les expressions et les booléens

Projet : Chance de survivre au naufrage du Titanic ?


Présentation du projet :

Vous allez travailler sur le jeu de données suivant (à télécharger): 

Ce jeu de données contient des informations sur une partie des passagers (plus exactement sur 891 passagers) du Titanic. Pour un petit rappel historique, vous pouvez consulter la page Wikipédia consacrée à ce paquebot : ici

Ouvrez le fichier « titanic.csv » à l’aide d’un tableur.

Vous devriez obtenir quelque chose qui ressemble à ceci :

Trouvez la signification des différents descripteurs : « PassengerId », « Survived », « Pclass »… Aide : 

L’objectif de ce projet est d’utiliser l’algorithme des k plus proches voisins afin de déterminer si les passagers ci-dessous auraient survécus au naufrage du Titanic.

PclassNameSexAgeSibSpParchTicketFareEmbarked
2Mr. Bidochon Robertmale371424437721.075C
2Mrs. Bidochon Raymondefemale361424437920.2175C
2Mrs. Bidochon Gisèlefemale113224438215.045C
2Mr. Bidochon René.male83224438312.945C
2Mr. Bidochon Eugène.male43213738310.17C
2Mr. Bidochon Louis.male132373811.13C

PARTIE 1 : Analyse des données (Data scientist)

Un travail de préparation des données va être nécessaire , vous allez donc devoir passer par quelques étapes que voici :

– Pour ceux qui ne souhaitent pas poursuivre la spécialité N.S.I vous pouvez opérer les changements directement avec le tableur.

– Pour ceux qui souhaitent poursuivre la spécialité N.S.I vous devez opérer les changements directement avec python.
Le fichier python ci-dessous, vous aidera faire les manipulations nécessaires).

Analyser ce fichier, combien y a t’il de fonctions,que font elles?

Pour la suite du projet vous pouvez travailler soit avec la liste de dictionnaire créé avec le programme, soit avec le fichier csv.

Toutes les colonnes ne vont pas forcement être pertinentes, par exemple, d’après vous, lors du naufrage, le nom du passager a-t-il eu une quelconque importance sur le fait qu’il ait ou non survécu ? (nous ne tiendrons pas compte du fait que certaines personnes aient pu être privilégié au vu de leur nom de famille, sur les 891 passagers présents dans le fichier titanic.csv, ce phénomène est négligeable).

Solution 1 avec le tableur:

En analysant le contenu du fichier titanic.csv (par exemple à l’aide d’un tableur), choisissez les descripteurs ( c’est à dire les colonnes) qui vous paraissent les plus pertinents. Vous effacerez les colonnes qui vous semblent inutiles directement dans le tableur ou avec python pour obtenir soit une liste de dictionnaire (comme Data dans le fichier donné ci dessus), soit un nouveau fichier titanic_V2.csv

Solution 2, avec python :

Nettoyer la liste de dictionnaire, en ne gardant pour chaque dictionnaire que les clés que vous jugez nécessaire.
Enregistrer votre fichier python.

Pour certains passagers, il manque des données. Par exemple, l’âge de certains passagers n’est pas renseigné. Une solution est de supprimer du fichier les passagers ayant des données incomplètes.

Supprimer du fichier les passagers ayant des données incomplètes pour obtenir un nouveau fichier titanic_V3.csv ou une nouvelle liste de dictionnaire avec les données incomplètes supprimées.


L’utilisation de l’algorithme des k plus proches voisins nous oblige à proscrire les données non numériques.
Par exemple, la colonne « Sex » ne peut pas être utilisée telle quelle, l’algorithme n’est pas capable de traiter les « male » et « female ».

Proposer une alternative pour remplacer les chaines de caracteres « male » et « female ».
Modifier certaines colonnes directement dans le tableur ou avec un script python pour obtenir un nouveau fichier titanic_V4.csv ou une nouvelle liste de dictionnaire.


Avec l’algorithme des k plus proches voisins nous sommes amenés à calculer des distances.
Comparer l’amplitude des valeurs de la colonne Pclass avec l’amplitude des valeurs de la colonne Age.

Amplitude des valeurs de la colonne Pclass :
Amplitude des valeurs de la colonne Age :

Code python pour obtenir cette amplitude à partir de titanic_V4.csv ou avec la liste de dictionnaire :
Une des conséquence de l’observation précédente est que le calcul de la distance ne va pas traiter de facon égalitaire les colonnes.
Pour rétablir l’équité nous allons procéder ainsi :
Pour chaque colonne :

  1. On repère la valeur minimale (v_min) et la valeur maximale ( v_max)
  2. On va diviser chacune des valeurs de la colonne par la diffrence v_max-v_min
    Exemple : Si une colonne contient les valeurs [5,4,1,11,7]
    v_min=1 et v_max=11
    Alors on divise toutes les valeurs par 8 ce qui donne [0.5,0.4,0.1,1.1,0.7]

Remarque :
Toutes les valeurs de toutes les colonnes seront comprises entre 0 et 1.
Cela nous garantie un traitement équitable entre les colonnes.

Faire les modifications nécessaires au fichier titanic_V4.csv pour garantir un équitable entre les colonnes. On nommera titanic_V5.csv le nouveau fichier obtenu. Vous devriez avoir un fichier comme celui-ci:

Partie 2: Graphique 3D

A l’aide du TP sur les k plus proches voisins, construire le graphique 3D à partir du fichier titanicV5.csv

Les survivants devront être en vert et les disparus en rouge, les personnes que vous testerez seront en bleu.

voici quelques liens ou faire des recherches:

1 er lien Les fiches CPGE

2 éme lien Machine learnia

Partie 3: Utilisation de l’algorithme des K plus proche voisins

A l’aide du TP sur les k plus proches voisins, (avec k=5) prédire quel(s) membre(s) de la famille Bidochons aurait(ent) survécu(s) au naufrage du Titanic ?

En utilisant l’algorithme proposé par scikit-learn
des k plus proches voisins établir votre programme python et donnez la liste des survivants en faisant varier k de 3 à 19 ( valeur impaire).

( c’est la ligne : from sklearn.neighbors import KNeighborsClassifier qui charge l’algorithme)