TP – Problème du sac à dos 27 mai 2008 1 Introduction L’objectif de ce TP vise à implémenter les heuristiques et algorithmes de bases pour le problème du sac à dos et de les confronter via un ensemble de tests commun. Dans une deuxième partie, on utilisera un solveur de programme linéaire et on statuera sur les avantages et inconvénients des différentes approches. On dispose d’un ensemble de classes de base (accessible ici http://www. loria.fr/~canon/pepites/base.zip). Les classes principales sont : KnapsackTest définit les donnés d’un problème (nombre d’item, poids, profits et capacité du sac à dos) ; KnapsackSolution définit une solution (booléen pour chaque item et problème associé) ; AlgorithmRandomSimple contient une fonction qui génère une solution aléatoire (tous les algorithmes devront reprendre le même modèle) ; Evaluator contient la fonction principale et permet de tester les algorithmes générés sur un même ensemble de tests (il est possible de définir la taille maximale des problèmes et le temps maximal passé dans chaque algorithme). La documentation est disponible ici http://www.loria.fr/~canon/pepites/ doc/. En cas de doute, le code est commenté et accessible. Il est impératif de ne pas tout comprendre (uniquement ce qui vous servira à construire vos méthodes). Le cours est accessible ici http://www.loria.fr/~canon/pepites/slideshow/ (temps de chargement long). 2 Approche algorithmique Tester le code en l’important dans un projet Eclipse et en lançant la classe Evaluator. 1 2.1 Génération aléatoire En repartant de la méthode de génération aléatoire donnée, proposer une nouvelle méthode aléatoire plus performante. L’idée consiste à disposer du plus grand nombre possible d’items dans la solution finale (à l’inverse, la méthode actuelle peut s’arrêter même s’il reste de la place). Insérer le nouvel algorithme dans la fonction main de la classe Evaluator et relancer le programme. 2.2 Heuristique gloutonne Réaliser une heuristique gloutonne (construction itérative en réalisant le meilleur choix à chaque étape). 2.3 Recherche exhaustive Réaliser une exploration exhaustive des solutions (par récursion). Comment de comporte cette méthode vis-à-vis des méthodes précédentes sur l’ensemble de tests ? 2.4 Méthode de branch and bound Repartir de la méthode précédente en y ajoutant des méthodes bornant supérieurement et inférieurement les solutions afin d’éliminer les branches de l’arbre de recherche qu’il est inutile d’explorer. Les bornes peuvent être obtenues grâce à l’heuristique gloutonne. Le gain est-il significatif dans sur l’ensemble de tests ? 2.5 Programmation dynamique Réaliser l’algorithme de programmation dynamique proposé en cours. L’article de Wikipedia http://en.wikipedia.org/wiki/Knapsack_problem fournit un complément d’informations. Quelle méthode se comporte le mieux sur l’ensemble de tests ? 3 Programmation linéaire On utilisera dans cette partie le solveur GLPK (GNU Linear Programming Kit) qui est libre, multiplateforme, dispose de méthodes pour la programmation en variables mixtes et d’une interface Java. La documentation de GLPK est disponible ici http://bjoern.dapnet.de/ glpk/refman48.pdf, et celle de l’interface Java, ici http://bjoern.dapnet. de/glpk/javadoc/index.html. 2 3.1 Importation et exemple simple Importer les bibliothèques (disponible ici http://bjoern.dapnet.de/glpk/ windows.zip) dans votre projet (Project -> Properties -> Java Build Path -> Libraries). Il faut importer le fichier jar et la bibliothèque dll. L’exemple (disponible ici http://www.loria.fr/~canon/pepites/ExempleMIP. java) consiste à résoudre le problème suivant (avec x1 , x2 et x3 entiers) : maximiser sujet à bornes Z = 10x1 + 6x2 + 4x3 x1 + x2 + x3 ≤ 100 10x1 + 4x2 + 5x3 ≤ 600 2x1 + 2x2 + 6x3 ≤ 300 x1 ≥ 0, x2 ≥ 0, x3 ≥ 0 Lancer l’exemple et observer le résultat. Il existe deux manières d’utiliser le solveur : soit par l’usage de primitive (comme dans l’exemple), soit par la lecture d’un fichier respectant un format donné (le fichier généré au format CPLEX exemple.pl peut ainsi être lu pas la primitive readCpxlp). 3.2 Résolution du problème du sac à dos Choisir une méthode pour utiliser le solveur (se reporter à la documentation adéquate pour la description de chaque primitive ou la spécification du format de fichier CPLEX) et résoudre le problème du sac à dos. Vérifier que le résultat est optimal (identique aux précédentes méthodes optimales). Statuer sur l’efficacité de cette méthode. 4 Sac à dos quadratique Étendre les classes existantes de manière à prendre en compte les profits pij . Adapter les algorithmes qui le nécessitent. Proposer une formulation linéaire pour le problème qui minimise le nombre de contraintes. 3