Ceci est une ancienne révision du document !
Warning: Undefined array key 1 in /home/goupillf/wiki.goupill.fr/lib/plugins/codeprettify/syntax/code.php on line 172
Warning: Undefined array key 1 in /home/goupillf/wiki.goupill.fr/lib/plugins/codeprettify/syntax/code.php on line 172
Warning: Undefined array key 1 in /home/goupillf/wiki.goupill.fr/lib/plugins/codeprettify/syntax/code.php on line 172
Warning: Undefined array key 1 in /home/goupillf/wiki.goupill.fr/lib/plugins/codeprettify/syntax/code.php on line 172
Warning: Undefined array key 2 in /home/goupillf/wiki.goupill.fr/lib/plugins/codeprettify/syntax/code.php on line 214
Warning: Undefined array key 2 in /home/goupillf/wiki.goupill.fr/lib/plugins/codeprettify/syntax/code.php on line 214
Warning: Undefined array key 2 in /home/goupillf/wiki.goupill.fr/lib/plugins/codeprettify/syntax/code.php on line 214
Warning: Undefined array key 2 in /home/goupillf/wiki.goupill.fr/lib/plugins/codeprettify/syntax/code.php on line 214
Warning: Undefined array key 2 in /home/goupillf/wiki.goupill.fr/lib/plugins/codeprettify/syntax/code.php on line 214
Warning: Undefined array key 2 in /home/goupillf/wiki.goupill.fr/lib/plugins/codeprettify/syntax/code.php on line 214
Warning: Undefined array key 2 in /home/goupillf/wiki.goupill.fr/lib/plugins/codeprettify/syntax/code.php on line 214
Warning: Undefined array key 2 in /home/goupillf/wiki.goupill.fr/lib/plugins/codeprettify/syntax/code.php on line 214
Table des matières
Problème du sac à dos
Qu'est-ce ?
Il s'agit d'un problème classique d'algorithmique.
- On dispose d'un sac de capacité C,
- d'un assortiment d'objets ayant tous un poids et une valeur.
- On cherche à placer des objets dans le sac en respectant la contrainte de capacité et en maximisant la valeur totale du contenu du sac.
Exemple : On dispose d'un sac d'une capacité de C = 15 kg et de la liste d'objets suivants :
| Objet | Valeur | Poids |
|---|---|---|
| A | 126 | 14 |
| B | 32 | 2 |
| C | 20 | 5 |
| D | 5 | 1 |
| E | 18 | 6 |
| F | 80 | 8 |
Algorithme glouton
L'algorithme glouton donne une réponse pas forcément optimale au problème posé mais il est simple :
- On trie le tableau selon un critère,
- puis on remplit le sac en prenant les objets dans l'ordre.
Valeur décroissante
Par exemple, trions le tableau par valeur décroissante.
| Objet | Valeur | Poids |
|---|---|---|
| A | 126 | 14 |
| F | 80 | 8 |
| B | 32 | 2 |
| C | 20 | 5 |
| E | 18 | 6 |
| D | 5 | 1 |
Puis complétons le sac en prenant, si possible, les objets dans l'ordre.
- On peut prendre A, ce qui occupe 14 kg de la capacité du sac,
- comme il ne reste que 1 kg de capacité, on ne peut pas prendre F, B, C, E.
- Enfin on peut prendre D.
Le sac contiendra A et D totalisant une valeur de 131.
Poids croissant
C'est un autre choix possible. Il aboutira à un contenu de sac différent.
| Objet | Valeur | Poids |
|---|---|---|
| D | 5 | 1 |
| B | 32 | 2 |
| C | 20 | 5 |
| E | 18 | 6 |
| F | 80 | 8 |
| A | 126 | 14 |
Rapport valeur / poids décroissant
On peut aussi faire des calculs avec les attributs des objets. Par exemple, il semble raisonnable d'évaluer le rapport valeur / poids afin de choisir en priorité les objets qui apportent de la valeur sans trop encombrer le sac.
| Objet | Valeur | Poids | rapport V/P |
|---|---|---|---|
| B | 32 | 2 | 16 |
| F | 80 | 8 | 10 |
| A | 126 | 14 | 9 |
| D | 5 | 1 | 5 |
| C | 20 | 5 | 4 |
| E | 18 | 6 | 3 |
Là encore on obtient un sac différent.
Remarquez qu'aucune de ces stratégies ne donne le meilleur sac, mais elles donnent de bons résultats.
Implémentation
Les objets
Les items disponibles seront représentés par des dictionnaires dans un tableau. Par exemple :
objets = [
{ "Nom":"A", "Valeur":126, "Poids":14 },
{ "Nom":"B", "Valeur":32, "Poids":2 },
{ "Nom":"C", "Valeur":20, "Poids":5 },
{ "Nom":"D", "Valeur":5, "Poids":1 },
{ "Nom":"E", "Valeur":18, "Poids":6 },
{ "Nom":"F", "Valeur":80, "Poids":8 }
]
Sac
Le contenu du sac sera lui aussi représenté par un tableau. Par exemple :
sac = [
{ "Nom":"A", "Valeur":126, "Poids":14 },
{ "Nom":"D", "Valeur":5, "Poids":1 }
]
fonctions utiles
Nous avons besoin des fonctions suivantes :
- ajouter un objet dans un sac si c'est possible,
- trier les objets dans un ordre défini,
- calculer la valeur d'un sac
Voici un modèle à compléter puis à exécuter :
- sacados.py
''' Algorithme glouton : problème du sac à dos ''' def poids_sac(sac): ''' sac: sac dont on veut la masse du contenu renvoie la masse totale contenue dans le sac ''' return 0 def ajouter_objet_dans_sac(C, sac, objet): ''' C: Capacité max du sac sac: sac dans lequel mettre l'objet objet: objet à mettre dans le sac ajoute l'objet dans le sac si c'est possible. renvoie True en cas de succès, False sinon ''' return False def tri(objets, critere): ''' objets: tableau des objets disponibles à trier critere: fonction qui pour un un objet donné renvoie sa valeur dans le tri exemple : si on tri par valeur décroissante, critere(objet) doit renvoyer la valeur de l'objet trie les objets selon le critère, toujours par ordre décroissant ne renvoie rien, trie objets en place ''' return def valeur_sac(sac): ''' sac: sac dont on veut la valeur renvoie la valeur totale de ce sac. ''' return 0 def glouton(objets, C, critere): ''' objets: tableau des objets que l'on peut mettre dans le sac C: capacité max du sac critere: fonction utilisée dans le tri renvoie le sac obtenu par l'algorithme glouton suivant le critère défini ''' return [] if __name__ == '__main__': # tests C = 15 objets = [ { "Nom":"A", "Valeur":126, "Poids":14 }, { "Nom":"B", "Valeur":32, "Poids":2 }, { "Nom":"C", "Valeur":20, "Poids":5 }, { "Nom":"D", "Valeur":5, "Poids":1 }, { "Nom":"E", "Valeur":18, "Poids":6 }, { "Nom":"F", "Valeur":80, "Poids":8 } ] def critere_valeur(objet): return objet["Valeur"] sac = glouton(objets, critere_valeur) print(sac)
Fonction lambda
En mathématique, une fonction consiste en l'association d'antécédents et d'images. On peut noter par exemple $x \mapsto 3x + 5$ l'idée que chaque nombre $x$ antécédent sera associer à l'image $3x+5$ : 0 est associé à 5 ; 1 est à 8 ; 2 est associé à 11 ; etc.
Notre fonction critere_valeur pourrait ainsi se noter $objet \mapsto objet[Valeur]$. On comprendrait ce que fait cette fonction sans la définir avant et sans lui donner de nom, il suffit de savoir que l'antécédent est objet et que l'image est objet["Valeur"].
Il existe une notation pour cela en Python :
lambda objet: objet["Valeur"]
C'est une fonction anonyme prenant comme argument (antécédent) objet et renvoie (image) objet["Valeur"].
Alors nous pouvons remplacer :
# code actuel, dans les tests
def critere_valeur(objet):
return objet["Valeur"]
sac = glouton(objets, critere_valeur)
# en utilisant lambda
sac = glouton(objets, lambda objet: objet["Valeur"])
Le résultat est le même.
autre critères
Exécutez le programme avec d'autres critères :
- rapport valeur / poids décroissant,
- poids croissant (il faut trouver une astuce puisque le tri se fait dans l'ordre décroissant du critère fourni !)
Essayez de le faire en utilisant lambda.
