Télécharger au format docx, pdf ou txt
Télécharger au format docx, pdf ou txt
Vous êtes sur la page 1sur 10

ALGORITHMES

I/ Recherche dichotomique dans un tableau trié

La recherche dichotomique est une manière efficace et rapide de rechercher un élément dans une structure de
données triée (pour nous, ce sera un tableau trié).

En effet, jusqu'à maintenant vous aviez peut-être l'habitude de parcourir un tableau du début jusqu'à ce que
l'on trouve la valeur, c'est-à-dire parfois jusqu'à la dernière case du tableau. Cette méthode est une recherche
séquentielle, facile à écrire et à mettre en oeuvre certes, mais n'est efficace en terme de temps d'exécution
que si le tableau parcouru est très petit.

La recherche dichotomique ne fonctionne que sur un tableau trié ! Il faut donc être sûr qu'il sera trié au
départ, ou passer par un algorithme de tri le cas échéant.

Nous allons utiliser le principe du ………………………………………………:

1. Partitionnant en divisant ce problème en sous-problèmes (supposés plus simples à résoudre);


2. Résolvant regner ces sous-problèmes individuellement;
3. Réunissant les résultats partiels pour résoudre le problème initial.

La partition divise la zone de recherche en deux parts de tailles égales et on se concentre uniquement sur la
bonne moitié en reproduisant ce mécanisme sur une nouvelle moitié et ainsi de suite de manière à ramener la
zone de recherche à une unité:

Principe de la recherche dichotomique:


1. On détermine l’élément m au milieu du tableau ;
2. Si c’est la valeur recherchée, on s’arrête avec un succès ;
3. Sinon, deux cas sont possibles :
(a) Si m est plus grand que la valeur recherchée, comme le tableau est trié, cela signifie qu’il suffit de continuer à
chercher dans la première moitié du tableau ;
(b) Sinon, il suffit de chercher dans la moitié droite.
4. On répète cela jusqu’à avoir trouvé la valeur recherchée, ou bien avoir réduit l’intervalle de recherche à un
intervalle vide, ce qui signifie que la valeur recherchée n’est pas présente.

Première NSI : ALGORITHMES dichotomie, k plus proches voisins, Gloutons Page 1 sur 9
À chaque étape, on coupe l’intervalle de recherche en deux, et on en choisit une moitié. On dit que l’on procède par
dichotomie, du grec dikha (en deux) et tomos (couper). On peut trouver un exemple animé de l’exécution de cet
algorithme ici: https://professeurb.github.io/articles/dichoto/

Algorithme:
g← 0 //L'élément de gauche a pour indice 0
d← longueur-1 //L'élément de droite a pour indice la longueur de la liste -1
//m est l'indice de l'élément du milieu, on le transforme en entier si nécessaire
tant que g<d : // Tant que la zone de recherche n'est pas nulle.
m← int((g+d)/2)
si v=t[m] alors //on a trouvé la valeur cherchée
renvoyer m
sinon si v<t[m] alors // la valeur est dans la 1 è r e moitié, donc la borne droite change
d'indice
d= m- 1
sinon // la valeur est dans la 2 è r e moitié, donc la borne gauche change d'indice
g = m+1
fin tant que

Exemple :
Trouver ou non la valeur 35 dans la liste triée t=[5,7,12,14,23,27,35,40,41,45]
2 possibilités de schéma :

L'idée est donc de définir le milieu du tableau (variable "mil") et de couper le tableau en 2, on se retrouve
avec 2 tableaux. On garde uniquement le tableau qui peut contenir la valeur recherchée. On recommence le
processus jusqu'au moment où l'on "tombe" sur la valeur recherchée ou que l'on se retrouve avec un tableau
contenant un seul élément : si l'élément unique du tableau n'est pas l'élément recherché, l'algorithme renvoie
FAUX.

Exercice :
Reproduire l'analyse avec t = [5, 7, 12, 14, 23, 27, 35, 40, 41, 45] et x = 9 à l’aide des deux schémas.
Attention, le schéma et l’algorithme présenté dans le cours sont différents : dans les schémas, le milieu
choisi correspond à la (g+d)//2 ième valeur alors que dans le cours, le milieu est la valeur dont l’indice est
(g+d)//2 . Mais les deux méthodes sont correctes…
[5, 7, 12, 14, 23]
[5, 7, 12] [14, 23]
[5,7] [ 12,14]

14 !=9

Première NSI : ALGORITHMES dichotomie, k plus proches voisins, Gloutons Page 2 sur 9
Terminaison de l'algorithme :

La fonction recherche_dichotomique contient une boucle non bornée, une boucle while, et pour être sûr de
toujours obtenir un résultat, il faut s’assurer que le programme termine, que l’on ne reste pas bloqué
infiniment dans la boucle. Pour prouver que c’est bien le cas, nous allons utiliser un variant de boucle.

Variant de boucle :
Il s’agit d’une quantité entière qui :
▷ doit être positive ou nulle pour rester dans la boucle
▷ doit décroître à chaque itération
Si l’on arrive trouver une telle quantité, il est évident que l’on va nécessairement sortir de la boucle au bout
d’un nombre fini d’itérations, puisqu'un entier positif ne peut décroître infiniment.

La valeur entière d-g est un variant de boucle qui décroît d'au moins une unité à chaque itération de la
boucle while , tout en restant positive ou nulle (g ≤ d dans la boucle ). Elle ne peut décroître indéfiniment.
On finira donc par avoir d < g et une sortie de boucle, si on n'a pas trouvé la valeur v avant cela bien
évidemment.

Programme Python :
Créer la fonction recherche_dichotomique qui permet pour un élément appelé element et une liste de
nombres triées liste_triee, de renvoyer un booleen True ou False suivant si l’élément est dans la liste ou non.
Variante : renvoyer le rang de la valeur si celle-ci est dans la liste.

Correction de l'algorithme: avec l'invariant de boucle 0 ≤ gauche ≤ milieu ≤ droite < len( liste_triee)
Soit on tombe sur l’élément à un moment, soit on arrive à gauche =droite, et si l’élément est dans le tableau,
liste_triee[gauche]≤ element ≤ liste_triee[droite]. Le résultat renvoyé est bien le bon.

Exercices :
1) Combien de valeurs sont examinés lors d’un appel à la fonction
recherche_dichotomique([0,1,1,2,3,5,8,13,21], 7) ?
2) Donner un exemple d’exécution de recherche_dichotomique où le nombre de valeurs examinées est
exactement quatre.
3) Modifier le programme recherche_dichotomique pour afficher le nombre total de tours de boucle
effectués par l’algorithme. Lancer le programme pour des tableaux de tailles différentes (taille 100, 1000,
10000 ).
4) Ecrire un programme qui permette à l’ordinateur de jouer à devine le nombre contre l’utilisateur. C’est
l’utilisateur qui choisit un nombre entre 0 et cent, et c’est l’ordinateur qui doit le trouver, le plus
efficacement possible. A chaque proposition faite par l’ordinateur, l’utilisateur doit donner une réponse sous
forme de chaine de caractère parmi « plus grand », «plus petit» ou «bravo».

Première NSI : ALGORITHMES dichotomie, k plus proches voisins, Gloutons Page 3 sur 9
II/ Algorithme des k plus proches voisins

On cherche à prédire la classe (le label) d'un nouvel élément (dont la position est connue) faisant partie
d'un ensemble de points dont les coordonnées et la classe sont connues. C'est-à-dire qu’à partir d’un jeu de
données et d’une donnée « cible », on détermine les k données les plus proches de la cible.

L’algorithme des k plus proches voisins, en anglais k-nearest neighbors, est l’un des algorithmes utilisés
dans le domaine de l’intelligence artificielle (IA), il appartient à la famille des algorithmes d’apprentissage
automatique (machine learning). L’idée d’apprentissage automatique ne date pas d’hier, puisque le terme de
machine learning a été utilisé pour la première fois par l’informaticien américain Arthur Samuel en 1959.

L’algorithme des k plus proches voisins est un algorithme d’apprentissage supervisé, il est nécessaire d’avoir
des données labellisées. À partir d’un ensemble E de données labellisées, il sera possible de classer
(déterminer le label) d’une nouvelle donnée (donnée n’appartenant pas à E). À noter qu’il est aussi possible
d’utiliser l’algorithme des k plus proches voisins à des fins de régression (on cherche à déterminer une
valeur à la place d’une classe), mais cet aspect des choses ne sera pas abordé ici.

Le principe peut être résumé par "dis-moi qui sont tes amis et je te dirai qui tu es" ou "celui qui marche avec
les hommes sages est un homme sage".

Exemple : classification de Pokémons (prépabac Hatier)


De façon très simpliste, admettons que les Pokémons ne possèdent que deux
caractéristiques : leurs points de vie et leur valeur d’attaque. On suppose qu’ils se répartissent en
deux types seulement : Eau et Psy.
Nom Écayon Deoxys Éoko Groret Tarpaud
Points de vie 49 50 80 90 90
Attaque 49 95 45 75 75
Type Eau Psy Psy Psy Eau

Dans un fichier pokemons.csv ci-contre on trouve une liste de 34 Pokémons.

À partir de cet échantillon, on veut pouvoir prédire la classification d’un


Pokémon mystère à partir de la donnée de ses points de vie et de sa valeur
d’attaque.

Première NSI : ALGORITHMES dichotomie, k plus proches voisins, Gloutons Page 4 sur 9
À partir des données représentées sur le diagramme, on veut prédire la classe d’un Pokémon qui à 65 de vie
et 40 en attaque. On trouve dans l’échantillon les 6 plus proches voisins :

Parmi ses 6 voisins, il y deux Pokémons de type Eau et quatre de type Psy. Il est donc probable que notre
Pokémon mystère soit un Pokémon de type Psy.

Formulation de l’algorithme :
Pour automatiser la classification, il faut formuler un algorithme de façon formelle. Pour prédire la classe
d’un Pokémon donné, il faut les données :
 Un échantillon de pokemon
 Un Pokémon_mystère dont pokemon mystere dont on veut predire la classification
 La valeur de k
Une fois ces données modélisées, la formulation de l’algorithme de prédiction est assez simple.
Algorithme :
1. Trouver dans l’échantillon, les k plus proches voisons de pokemon mystere
2. Parmi ces proches voisins, trouver la classification majoritaire
3. Renvoyer la classification majoritaire

Remarque :
La valeur k = 6 est ici un choix arbitraire. Cette valeur doit néanmoins être choisie judicieusement : trop
faible, la qualité de la prédiction diminue ; trop grande la qualité de la prédiction diminue aussi. Par exemple
avec k = 34, la prédiction sera toujours Psy (classe majoritaire dans l’échantillon).

Implémentation en Python dans le cas général :


On mettra en œuvre trois fonctions:
1. Distance entre deux points
Suivant que l'on raisonne à une, deux ou trois dimensions, le calcul de la distance varie.
Nous conviendrons d'utiliser la valeur absolue de la différence des abscisses entre deux points dans un
espace à une dimension et la distance euclidienne dans un espace à deux dimensions.

Exercice :

a. Écrire une fonction distance1(x1,x2) qui renvoie la distance entre deux points d'abscisses x1 et x2
dans un espace à une dimension. Tester la fonction. ( distance (point1, point2) = |x1 – x2| )
b. Écrire une fonction distance2(c1,c2) qui renvoie la distance entre deux points et qui prend en
paramètre c1 et c2 des tuples du type (x,y). Tester la fonction.
(distance (point1, point2) = √ ( x 2−x 1 )2 + ( y 2− y 1 )2 )

Première NSI : ALGORITHMES dichotomie, k plus proches voisins, Gloutons Page 5 sur 9
2. Recherche des k plus proches voisins

Il nous faut maintenant déterminer les k données de E les plus proches d'une donnée étrangère « cible ».
« cible » n'appartient pas à E. Pour cela on peut, par exemple, suivre l'algorithme naïf suivant (en pseudo-
code):
Données :
 Une liste de données de taille n : liste
 Une donnée cible : cible
 Un entier k plus petit que n
 Une règle permettant de calculer la « distance » entre deux données
Résultat : les k plus proches voisins de la cible

Algorithme :
1. Trier les données de la liste selon la distance croissante avec la donnée cible
2. Kvoisins est la liste de k premières données de la liste triée
3. renvoyer Kvoisins

Exercice :
a. Écrire une fonction Kvoisins(L,k,cible,d) qui prend en arguments une liste L de coordonnées des points
de E, un entier k , cible la position d'un nouvel élément et d la distance utilisée dans le problème.
Elle renvoie la liste des indices dans L des k plus proches voisins de cible.
b. Tester votre fonction avec E=list(range(1000)) , Kvoisins(E,1,15.2,distance1) et
Kvoisins(E,4,15.2,distance1)

4. Attribution de classe
Il resterait à déterminer la classe la plus fréquente parmi les k voisins de l'élément cible pour prédire la classe
de cible en écrivant une fonction predireClasse(L,classes,k,cible) prenant en arguments la liste L des
positions des éléments de E, la liste des classes des éléments de E (chaines de caractères), k un entier et cible
l'élément "à prédire".

Exercice :
Voici des formes géométriques, des carrés et des triangles. Notre cible est le rond vert.

La liste des positions des éléments est liste = [0.5,1.0,2.0,3.7,5.1,6.0,7.0]

Le rond vert ne figure pas dans cette liste !!!!!

La liste des classes des éléments est classes = [’T’,’C’,’C’,’T’,’T’,’C’,’C’]

Première NSI : ALGORITHMES dichotomie, k plus proches voisins, Gloutons Page 6 sur 9
1. Chercher les 3 plus proches voisins à l’aide de Kvoisins
2. Écrire la fonction predireClasse permettant de prédire la classe du rond vert.

Pseudo-code :
voisins←Kvoisins(L,k,cible,d)
classesPossibles←['C','T'] # Toutes les formes géométriques possibles
frequences←[0]*len(classesPossibles) #on initialise autant de compteurs à 0 qu'il y a de classes possibles, ici 2
pour v dans voisins: #on parcourt les indices des k plus proches voisins
si classes[v] est un carré
ajouter 1 à frequences[0] #on incrémente de compteur de 1
sinon
ajouter 1 à frequences[1]
fin si
fin Pour
#on recherche l'indice de la fréquence max
indice←indice du maximum de frequences
renvoyer classesPossibles[indice] #on renvoie la prédiction de la classe de x

III/ Algorithme GLOUTON

 Certains algorithmes se positionnent sur les problèmes d’optimisation c’est-à-dire parcours d’espace de
recherche avec recherche de la meilleure solution (fonction de coût qui doit être minimisée).
 Les algorithmes gloutons parcourent l’espace de recherche sans jamais remettre en cause les choix
faits.
 A chaque étape, on fait le meilleur choix et on passe à l’étape suivante.
 Suivant la nature du problème on peut se garantir d’une solution optimale ou d’une solution qui ne
correspond qu’à un maximum local (rendu de monnaie contre exemples).

C’est un algorithme en général simple mais souvent inutilisable en machine à cause de son coût. C’est aussi
souvent une solution intéressante mais pas toujours la meilleure.

1. Le problème du rendu de monnaie


Principe :
On souhaite rendre une somme en utilisant le moins de pièces (ou de billets) possibles. Le principe de
l’algorithme consiste à répéter le choix de la pièce de plus grande valeur qui ne dépasse pas le somme
restante.
Remarque :
On dit qu’il s’agit d’un algorithme glouton car il choisit la pièce la plus grosse à chaque étape sans réfléchir
à la suite.

Première NSI : ALGORITHMES dichotomie, k plus proches voisins, Gloutons Page 7 sur 9
Exemple :
On veut programmer une caisse automatique pour qu’elle rende la monnaie de façon optimale, c'est-à-dire
avec le nombre minimal de pièces.
La valeur des pièces et des billets à disposition sont : 1, 2, 5, 10, 20, 50, 100 et 200 euros.
On dispose d’autant d’exemplaires qu’on le souhaite de chaque pièce et chaque billet.
Anaïs veut acheter un objet qui coûte 53 euros. Elle paye avec un billet de 100 euros. La caisse automatique
doit lui rendre 47 euros.

Données : la somme à rendre et la liste des pièces à disposition classée dans l’ordre décroissant.
Résultat : une liste de pièces et de billets à rendre.

Algorithme :
 Initialiser monnaie à liste vide
 Initialiser somme_restante à somme
 Tant que somme_restante est strictement positive
o On choisit dans liste la plus grande valeur qui ne dépasse pas la somme restante,
o On ajoute cette valeur à monnaie,
o Somme restante = somme restante – valeur choisie ;
 Renvoyer monnaie

Solution : On a
somme = 47
liste = [200,100,50,20,10,5,2,1]

Initialisation monnaie = [] somme_restante = 47


Etape 1 monnaie = [20] somme_restante = 27
Etape 2 monnaie = [20,20] somme_restante = 7
Etape 3 monnaie = [20,20,5] somme_restante = 2
Etape 4 monnaie = [20,20,5,2] somme_restante = 0

Résultat :
Ici notre algorithme glouton donne la solution optimale globale.

Autre exemple :
Si notre caisse automatique doit rendre une somme de 63 euros, mais qu’elle ne dispose plus de billets de 5
euros ni de 10 euros.
somme = 63
liste = [200,100,50,20,2,1]
Résultat : [20,20,20,2,1]
C’est une solution optimale locale, la solution optimale globale serait

Programme Python :
Créer la fonction rendu_monnaie qui permet pour un montant appelé somme que l’on doit rendre et une liste
de pièces disponibles pieces, de renvoyer la liste des pièces à rendre (la liste monnaie)

2. Le problème du sac à dos

Première NSI : ALGORITHMES dichotomie, k plus proches voisins, Gloutons Page 8 sur 9
Le problème du sac à dos, (aussi noté KP pour « Knapsack Problem » en anglais) est lui aussi un
problème d’optimisation. Il permet de résoudre le problème du remplissage d’un sac à dos. On dispose
pour cela de plusieurs objets (chaque objet possède une valeur et un poids). Seulement le sac ne peut pas
supporter plus d’un certain poids. Aussi on va devoir choisir tout ou une partie des objets. Les objets mis
dans le sac à dos doivent maximiser la valeur totale dans le sac, sans toutefois dépasser le poids
maximum.

valeur : 5 et poids : 0,5

valeur : 2 et poids : 1

valeur : 3 et poids : 4

valeur : 1 et poids : 0,2

L’algorithme glouton consiste à choisir à chaque étape du remplissage l’objet de plus grande valeur. On
répète les étapes de remplissage juste avant que le poids maximal soit atteint. On supposera que chaque
objet existe de manière unique.

Remarque :
On dit à nouveau qu’il s’agit d’un algorithme glouton car il choisit (tel un brigand) l’objet de plus grande
valeur à chaque étape sans réfléchir à la suite.

Exemple :
Pour le problème illustré ci-dessus, on choisit parmi les objets : goûter, jumelles, livre, chat en peluche mais
le sac à dos ne doit pas peser plus de 5 kg.
La solution la plus simple est d’utiliser un algorithme glouton mais il faut garder en tête que ce n’est pas
toujours une solution optimale.
Pour cela, on choisit d’abord :
 Les jumelles (de valeur 5), le sac pèse alors 0,5 kg,
 Le chat en peluche (de valeur 3), le sac pèse 4,5 kg,
 On ne peut pas prendre le goûter (de valeur 2) car il ferait dépasser les 5 kg
 On prend donc l’objet de valeur suivante : le livre et le poids du sac vaut 4,7 kg.
 L’algorithme s’arrête.
Données : liste de valeur des objets et de leur poids du type
objets = [[valeur,poids],[…,…],…]
le poids maximal poids_max
Résultat : les objets choisis objets_choisis

Algorithme :

Première NSI : ALGORITHMES dichotomie, k plus proches voisins, Gloutons Page 9 sur 9
 Trier la liste objets par ordre décroissant selon la valeur de chaque objet
 Initialiser le poids du sac à 0
 Initialiser la liste des objets choisis à []
 Renvoyer la liste objets_choisis
 Parcourir la liste objet
o Si le poids du sac est inférieur au poids_max :
 Ajouter l’objet à la liste objets_choisis
 Ajouter le poids de l’objet au poids du sac
 Renvoyer la liste objets_choisis

Programme Python :
Créer une fonction remplir_sac qui permet pour un poids maximum appelé poids_max et une liste triée
d’objets objets, de renvoyer la liste des objets mis dans le sac (la liste objets_choisis)

Remarque :
La liste objets n’étant pas triée par ordre décroissant de valeur qui est le premier élément il faut utiliser par
exemple list(reversed(sorted(objets)))

Affichage du shell :

Sources : NSI ellipses Cécile Canu, prépabac NSI, V. Cornet-Berry, M-S Chapuis,
https://pixees.fr/informatiquelycee/n_site/isn_dicho_algo.html

Première NSI : ALGORITHMES dichotomie, k plus proches voisins, Gloutons Page 10 sur 9

Vous aimerez peut-être aussi