- Accueil
- TUTORIELS
- LES ALGORITHMES GLOUTONS
- Quand le glouton se trompe
CHAPITRE 3 : QUAND LE GLOUTON SE TROMPE
Tonton Émile fait la ligne Yaoundé–Douala. Dans la soute de son car, il lui reste 15 kilos à vendre pour le compte de commerçants. Plusieurs marchandises lui sont proposées. Il doit choisir, et il va se tromper.
Ce qu'on lui propose
| Marchandise | Poids | Valeur | Valeur au kilo |
|---|---|---|---|
| Poivre de Penja | 9 kg | 100 000 FCFA | 11 111 FCFA/kg |
| Cacao | 12 kg | 70 000 FCFA | 5 833 FCFA/kg |
| Safou | 2 kg | 10 000 FCFA | 5 000 FCFA/kg |
| Ndolé séché | 7 kg | 30 000 FCFA | 4 286 FCFA/kg |
| Miel d'Oku | 5 kg | 20 000 FCFA | 4 000 FCFA/kg |
Les sacs ne se coupent pas : on prend la marchandise entière, ou on la laisse. C'est ce qu'on appelle le sac à dos 0-1 : zéro ou un exemplaire, jamais une moitié.
Le raisonnement de Tonton Émile
Il est transporteur depuis vingt ans, et sa règle est simple : je charge d'abord ce qui rapporte le plus au kilo. C'est un critère glouton, et il est tout à fait raisonnable.
- Le poivre de Penja rapporte 11 111 FCFA/kg. Il le prend. 9 kg chargés, 6 restants.
- Le cacao vient ensuite, mais il pèse 12 kg. Impossible.
- Le safou ? 2 kg, ça rentre. Il le prend. 11 kg chargés, 4 restants.
- Le ndolé pèse 7 kg, le miel 5 kg. Ni l'un ni l'autre ne rentre dans les 4 kg qui restent.
Chargement final : 11 kg pour 110 000 FCFA
Ce qu'il aurait fallu faire
En testant les 32 combinaisons possibles, on trouve mieux :
Poivre (9 kg) + Miel d'Oku (5 kg) = 14 kg pour 120 000 FCFA
Tonton Émile a perdu 10 000 FCFA, soit 8,3 % de ce qu'il pouvait gagner. Sur une ligne qu'il fait deux fois par semaine, cela fait plus d'un million de francs sur l'année.
Où est l'erreur ?
Elle n'est pas dans le critère. Le safou rapporte bien plus au kilo que le miel : 5 000 contre 4 000. Le glouton a correctement appliqué sa règle.
L'erreur est ailleurs : en prenant le safou, qui ne pèse que 2 kg, Tonton Émile s'est retrouvé avec 4 kg inutilisables. Trop peu pour le miel, trop peu pour le ndolé. Ces 4 kg sont partis à vide.
Le miel rapporte moins au kilo, mais il remplit mieux le car. Le glouton ne sait pas voir cela : il regarde les marchandises une par une, pas la place qu'elles laissent derrière elles.
C'est le défaut structurel du glouton. Il évalue chaque candidat isolément. Il lui faudrait anticiper : se demander « si je prends celui-ci, qu'est-ce que je pourrai encore prendre après ? », et c'est précisément ce qu'il ne fait jamais.
Anticiper, c'est le travail de la programmation dynamique, plus lente mais exacte.
Le code, quand même
Même imparfait, l'algorithme reste utile. Le voici :
def charger(marchandises, capacite):
# marchandises : liste de (nom, poids, valeur). Renvoie (valeur, chargement)
# on trie du plus rentable au kilo au moins rentable
par_densite = sorted(marchandises,
key=lambda m: m[2] / m[1],
reverse=True)
poids, valeur, pris = 0, 0, []
for nom, p, v in par_densite:
if poids + p <= capacite: # ca rentre encore
pris.append(nom)
poids += p
valeur += v
return valeur, pris, poids
>>> charger(MARCHANDISES, 15)
(110000, ['Poivre de Penja', 'Safou'], 11)
Et la force brute ?
from itertools import combinations
def charger_exact(marchandises, capacite):
# Teste toutes les combinaisons. Exact, mais exponentiel
meilleur = (0, ())
for taille in range(len(marchandises) + 1):
for essai in combinations(marchandises, taille):
poids = sum(m[1] for m in essai)
if poids <= capacite:
valeur = sum(m[2] for m in essai)
if valeur > meilleur[0]:
meilleur = (valeur, essai)
return meilleur
Sur cinq marchandises, c'est instantané : 32 combinaisons. Sur cinquante, c'est un million de milliards : inenvisageable.
Alors, faut-il jeter le glouton ?
Non. Il faut savoir ce qu'on achète.
| Glouton | Force brute | |
|---|---|---|
| Résultat | 110 000 FCFA | 120 000 FCFA |
| Écart | 8,3 % | |
| Temps sur 5 objets | immédiat | immédiat |
| Temps sur 50 objets | immédiat | des siècles |
Perdre 8 % sur un calcul instantané est souvent un bon marché. Et on peut démontrer que ce glouton-là ne descend jamais en dessous de la moitié de l'optimum : il est mauvais, mais pas catastrophique.
Au chapitre suivant, nous changerons une seule règle du problème, et le même glouton deviendra parfaitement optimal.
À retenir
- Sac à dos 0-1 : on prend l'objet entier ou pas du tout.
- Le critère « le plus rentable au kilo » est raisonnable mais pas optimal.
- Le glouton échoue parce qu'il ignore la place qu'un choix laisse derrière lui.
- Ici : 110 000 contre 120 000 FCFA, soit 8,3 % perdus.
Exercices d'application
Voir le corrigeMasquer le corrige
Il y a 2⁵ = 32 combinaisons en tout, dont certaines dépassent les 15 kg. Listons celles qui tiennent et rapportent le plus (P = poivre 9 kg, C = cacao 12 kg, S = safou 2 kg, N = ndolé 7 kg, M = miel 5 kg) :
| Chargement | Poids | Valeur |
|---|---|---|
| P + M | 14 kg | 120 000 |
| P + S | 11 kg | 110 000 |
| P + N | 16 kg | dépasse |
| C + S | 14 kg | 80 000 |
| C | 12 kg | 70 000 |
| N + M + S | 14 kg | 60 000 |
Le poivre seul vaut déjà 100 000 : toute bonne solution le contient. Avec 6 kg restants, le choix se réduit au safou (2 kg, 10 000) ou au miel (5 kg, 20 000). Le miel gagne.
P + M = 120 000 FCFA est bien l'optimum.
Voir le corrigeMasquer le corrige
La vanille vaut 15 000 FCFA/kg : elle devient la plus rentable, devant le poivre (11 111).
Glouton :
vanille 1 kg -> 1 kg, 15 000 reste 14 kg
poivre 9 kg -> 10 kg, 115 000 reste 5 kg
cacao 12 kg -> ne rentre pas
safou 2 kg -> 12 kg, 125 000 reste 3 kg
ndole 7 kg -> ne rentre pas
miel 5 kg -> ne rentre pas
total : 12 kg, 125 000 FCFAOptimum : vanille + poivre + miel = 1 + 9 + 5 = 15 kg pour 15 000 + 100 000 + 20 000 = 135 000 FCFA.
Le glouton perd encore 10 000 FCFA, et pour la même raison : le safou lui a mangé 2 kg qui manquaient au miel. Ajouter un objet n'a rien corrigé : le défaut est dans la méthode, pas dans les données.
Voir le corrigeMasquer le corrige
Trois critères sont couramment tentés :
| Critère | Chargement | Valeur |
|---|---|---|
| Valeur au kilo décroissante | Poivre + Safou | 110 000 |
| Valeur absolue décroissante | Poivre + Safou | 110 000 |
| Poids croissant | Safou + Miel + Ndolé | 60 000 |
La valeur absolue prend d'abord le poivre (100 000), puis le cacao ne rentre pas, puis le ndolé (30 000) ne rentre pas dans 6 kg, puis le miel (20 000) ne rentre pas non plus… puis le safou. Même résultat.
Le poids croissant est franchement mauvais : il remplit le car de petites marchandises sans valeur.
Aucun critère glouton ne trouve 120 000 ici, et ce n'est pas un hasard : on a démontré qu'aucun algorithme glouton ne résout le sac à dos 0-1 de façon optimale dans tous les cas. Changer de critère déplace l'erreur, il ne la supprime pas.
Cherchez avant d'ouvrir le corrige : c'est en butant sur les difficultes que l'on progresse.
Questions / Réponses
Ajouter un commentaire