Problème
On dispose d'un set

contenant

objets. Chaque objet

possède une valeur

et un poids

.
On souhaiterait prendre une partie

de ces objets dans notre sac-à-dos, malheureusement, ce dernier dispose d'une capacité limitée

. On ne pourra pas toujours mettre tous les objets dans le sac étant donné que la somme des poids des objets ne peut pas dépasser la capacité maximale.
On va cependant chercher à maximiser la somme des valeurs des objets qu'on va emporter avec soi.
Mathématiquement, cela se traduit par

.
Solution naïve
On pourrait être tenté d'énumérer toutes les combinaisons d'objets possibles qui satisfont à la capacité maximale du sac ou qui s'en rapprochent (le sac ne doit pas être obligatoirement rempli à fond). Néanmoins, on arrive rapidement à des calculs lourds, rendant le programme inefficace.
À nouveau, la solution de force brute fonctionne, mais ne doit pas être choisie.
Comme vous vous en doutez, on va résoudre ce problème au moyen de la méthode gloutonne.
Méthode
L'idée à suivre, si on veut développer une méthode gloutonne, est d'ajouter les objets de valeurs élevées en premier, jusqu'à saturation du sac.
Cette méthode est parfois efficace, mais parfois pas, on verra ses limites dans la prochaine partie.
Prenons un exemple, afin d'illustrer cela.
Supposons qu'on dispose d'un sac de capacité

et du set d'objets que voici
| Objets |
A |
B |
C |
D |
E |
F |
G |
H |
I |
J |
K |
L |
M |
N |
| Valeurs |
4 |
3 |
8 |
5 |
10 |
7 |
1 |
7 |
3 |
3 |
6 |
12 |
2 |
4 |
| Poids |
2 |
2 |
5 |
2 |
7 |
4 |
1 |
4 |
2 |
1 |
4 |
10 |
2 |
1 |
Set d'objets à notre disposition
Suivons le principe de la méthode et prenons les objets de meilleure valeur.
Ça nous donne le sous-set d'objets suivant :
L(12,10); E(10,7); C(8,5); F(7,4)
Notre sac est tout juste saturé et la somme des valeurs des objets qu'il contient est de 37.
Cette solution est-elle optimale ?
Rien,
a priori, ne garantit l'optimalité de cette solution. Nous verrons plus tard ce qu'il en est.
Implémentation
On va reprendre l'idée, le principe des algorithmes gloutons et déterminer des solutions locales au problème.
À partir d'une liste, dont les éléments sont des triplets [objet,valeur,poids], triée selon l'ordre décroissant des valeurs, on va remplir le sac à dos jusqu'à saturation.
On va ainsi parcourir tous les éléments à notre disposition via la liste et on ajoutera ceux dont le poids, cumulé aux poids des objets déjà dans le sac, est inférieur à la capacité totale du sac.
Lorsque la capacité totale est dépassée, ça signifie soit que le sac est plein, soit que l'objet qu'on veut insérer est trop lourd.
Il vient donc l'implémentation suivante :
Code : Python 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15 | def knapSack(totalWeight, objects):
currentWeight = 0
subSet = []
for counter in range(len(objects):
if currentWeight + objects[counter][-1] <= totalWeight:
currentWeight += objects[counter][-1]
subSet.append(objects[counter])
return subSet
def retrivevingData():
objects = input("Veuillez entrer le set d'objets sous la forme \"liste de liste\" (e.g. [[objet1, valeur1, poids1],[objet2,valeur2,poids2]]) par ordre décroissant de valeur :")
totalWeight = input("Veuillez entrer la capacité maximale de votre sac à dos :")
return knapSack(totalWeight, objects):
print "La proposition de la méthode gloutonne est :", retrievingData()
|
Notons que la terminaison de la boucle est garantie, puisqu'on itère sur une séquence finie.