IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

Algorithmes et structures de données Discussion :

Diviser le traitement du sac a dos


Sujet :

Algorithmes et structures de données

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre éclairé
    Inscrit en
    Décembre 2005
    Messages
    271
    Détails du profil
    Informations forums :
    Inscription : Décembre 2005
    Messages : 271
    Par défaut Diviser le traitement du sac a dos
    (Re)Bonjour,

    J ai un algorithme qui explore toutes les solutions pour un cas a dos de poids p et n objets contant chacun une valeur v et un poids w

    Le but est de remplir le sac a dos au maximum (sans depasser le poids p) et avec la combinaison d'objets ayant la plus grande valeur.

    Mon algo est rapide pour les poids inferieur a 20 et sur une une sequence de 50 objets. Il me donne la combinaison optimale

    J aimerais augmenter le poids jusqu a 100, mais le traitement est tres long

    Je me demande si il serai possible de calculer sur un poids de 10 la combinaison optimale, pui de recalculer avec un poids de 10 sur la liste d'objets - la combinaison precedemment trouvé, et ainsi de suite jusqu a 100 puis de concatener toutes les solutions trouvées a chaque fois.

    Est ce que je trouverai la solution optimale comme cela ? Ou est ce qu il faudra un traitement intermediaire ?


    Merci d avance

  2. #2
    Membre chevronné
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Mai 2006
    Messages
    507
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Pas de Calais (Nord Pas de Calais)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : Communication - Médias

    Informations forums :
    Inscription : Mai 2006
    Messages : 507
    Par défaut
    Salut,

    Tel que, ce n'est pas évident que tu trouves la solution. Déjà tu vas négliger tous les objets qui font plus de 10kg... Ensuite, il est possible que tu ne remplisses pas complétement certains sacs de 10kg, il faudrait alors relancer l'algorithme sur la somme des espaces vides de chacuns des sacs à dos. Cependant, tu vas là encore avoir une petite capacité, et tu risques à nouveau de négliger certains objets plus lourd qui pourrait intervenir dans la combinaison optimale pour un sac de 100kg...

    Ceci dit, il y a peut-être des solutions à ces problèmes...

  3. #3
    Membre éclairé
    Inscrit en
    Décembre 2005
    Messages
    271
    Détails du profil
    Informations forums :
    Inscription : Décembre 2005
    Messages : 271
    Par défaut
    Je pourrai lancer la procedure avec un pas egale au poids de l objet le plus gros, pour eviter de les negliger, et reporter l espace non remplie sur la procedure suivante

    Mais ce qui me fait soucis, c est les objets qui sont la "pour combler l espace restant" ...

  4. #4
    Membre chevronné
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Mai 2006
    Messages
    507
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Pas de Calais (Nord Pas de Calais)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : Communication - Médias

    Informations forums :
    Inscription : Mai 2006
    Messages : 507
    Par défaut
    Citation Envoyé par Treuze
    Je pourrai lancer la procedure avec un pas egale au poids de l objet le plus gros, pour eviter de les negliger, et reporter l espace non remplie sur la procedure suivante

    Mais ce qui me fait soucis, c est les objets qui sont la "pour combler l espace restant" ...
    Je suis pas certain que cela marche...

    Petit exemple : Prenons un sac de 6kg avec 3 objets O1 de 2kg chacun, un objet O2 de 2,5kg et un dernier O3 de 3 kg.
    D'après ton découpage tu ferais, d'abord un remplissage d'un sac de 3kg. Bien, tu le remplis avec O3. Puis, il te reste un sac de 3kg que tu remplis avec O2 pour optimiser. Resultat : tu as remplis ton sac de 6kg à 5,5kg avec les objets O2 et O3, alors que la (seule) solution optimale était de remplir le sac avec les trois objets O1... Le sac aurait été rempli à 6kg...

    C'est pour cette raison que je suis un peu septique au sujet du découpage... tu risques de passer à coté de la solution.

  5. #5
    Membre chevronné
    Homme Profil pro
    /
    Inscrit en
    Février 2003
    Messages
    434
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 44
    Localisation : Belgique

    Informations professionnelles :
    Activité : /

    Informations forums :
    Inscription : Février 2003
    Messages : 434
    Par défaut
    Si je peux apporter ma petite pierre à l'édifice voici comment j'envisagerais les choses

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
     
    Calculer le "rendement" des objets(valeur/poids)
     
    Remplir()
    	Tant que Poids_restant > poids de l'objet le plus leger
    		(Objet à ajouter) = Objet ou rendement est maximum
    		Nombre Objet = Poids_restant / Poids((Objet à ajouter))
    		Ajouter(Nombre Objet, Objet) dans le sac
    		Poids_restant = Poids_restant - Nombre Objet * Poids((Objet à ajouter))
    		Supprimer les objet ou poids(Objet) > Poids_restant
    		Remplir()
    	Fin tant que
    Fin Remplir

  6. #6
    Membre émérite
    Avatar de mamelouk
    Profil pro
    Inscrit en
    Mai 2005
    Messages
    867
    Détails du profil
    Informations personnelles :
    Localisation : France, Rhône (Rhône Alpes)

    Informations forums :
    Inscription : Mai 2005
    Messages : 867
    Par défaut
    Salut,

    Je suis encore un peu noobs, mais c'est pas un problème classique de "bin packing", qui se résout classiquement à l'aide d'une recherche de type A* ?

  7. #7
    Rédacteur
    Avatar de Zavonen
    Profil pro
    Inscrit en
    Novembre 2006
    Messages
    1 772
    Détails du profil
    Informations personnelles :
    Âge : 78
    Localisation : France

    Informations forums :
    Inscription : Novembre 2006
    Messages : 1 772
    Par défaut Eclaircissements
    Citation Envoyé par Treuze
    (Re)Bonjour,

    J ai un algorithme qui explore toutes les solutions pour un cas a dos de poids p et n objets contant chacun une valeur v et un poids w
    Je n'ai pas très bien compris les contraintes. Ce qui est limité, ce sont les objets eux-mêmes ou bien les types d'objets.
    Dans le premier cas il faut rajouter des paramètres:
    p1: nombre d'objets (disponibles) de poids w1 et de valeur v1.
    ............................
    pk: nombre d'objets de poids wk et de valeur vk
    avec p1+p2+....+pk=50
    ou alors:
    dans le second cas on affirme qu'il y a des objets
    de type T1: poids w1, valeur v1
    .......
    de type T50; poids w50, valeur v50
    Cela dit il faut apporter quelques précisions sur les valeurs:
    Accepte-t-on des valeurs négatives ?
    Y-a-t'il des trous dans les valeurs où sont-elles en progression arithmétique?
    Les solutions dépendent évidemment de la formulation précise.
    Des algorithmes on peut en trouver dans tous les cas. On peut même en optimiser certains (cela semble déjà avoir été fait), mais j'ai le sentiment qu'on dépasse assez vite les capacités d'un PC.
    Ce qu'on trouve est plus important que ce qu'on cherche.
    Maths de base pour les nuls (et les autres...)

  8. #8
    Membre expérimenté
    Profil pro
    Inscrit en
    Janvier 2004
    Messages
    192
    Détails du profil
    Informations personnelles :
    Âge : 44
    Localisation : France

    Informations forums :
    Inscription : Janvier 2004
    Messages : 192
    Par défaut
    As-tu déjà regardé cette page ?
    http://fr.wikipedia.org/wiki/Probl%C...sac_%C3%A0_dos


    Dans la section "Programmation dynamique" (5.1), tu as l'algorithme classique de résolution de ce problème, plutôt simple et relativement efficace selon ton profil de données.
    Si tu veux développer ta propre méthode, tu peux t'en servir comme base et trouver des améliorations "maison" (avoir une bonne solution sous la main et t'en servir pour interdire certaines possibilités par exemple...).

  9. #9
    Rédacteur
    Avatar de Zavonen
    Profil pro
    Inscrit en
    Novembre 2006
    Messages
    1 772
    Détails du profil
    Informations personnelles :
    Âge : 78
    Localisation : France

    Informations forums :
    Inscription : Novembre 2006
    Messages : 1 772
    Par défaut Modeste contrib
    Citation Envoyé par borisd
    As-tu déjà regardé cette page ?
    http://fr.wikipedia.org/wiki/Probl%C...sac_%C3%A0_dos


    Dans la section "Programmation dynamique" (5.1), tu as l'algorithme classique de résolution de ce problème, plutôt simple et relativement efficace selon ton profil de données.
    Si tu veux développer ta propre méthode, tu peux t'en servir comme base et trouver des améliorations "maison" (avoir une bonne solution sous la main et t'en servir pour interdire certaines possibilités par exemple...).
    Merci à borisd pour ses eclaircissements. Voici ce que la lecture de l'article m'inspire:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    Supposons qu'on travaille, pour fixer les idées avec 5 objets
    dont les poids sont : 12,4,2,1,1
    et dont les valeurs sont 4,10,2,2,1
    On ne fait que reprendre l'exemple du Wiki  avec le poids maximum =15 
     
    L'idée est de combiner trois approches données dans l'article pour générer un arbre des 'possibles' aussi réduit que possible.
     
    Une 'possibilité' est donc une suite arbitraire de 5 éléments binaires
    par exemple {1,0,1,0,1}
    Pour chaque possibilité on peut donc calculer le poids et la valeur.
    Le problème est que les possibilités sont en trop grand nombre pour les générer toutes, ce qui rend les algorithmes naïfs inopérants.
    On peut d'abord utiliser l'algorithme glouton pour obtenir une borne inférieure du max, disons k,  mais on peut le faire aussi d'autres manières.
    Il est très important de démarrer l'algorithme avec une telle borne k aussi haute que possible.
    Cela dit on considère la relation d'inclusion entre parties.
    A inclus dans B équivaut à A inter B = A équivaut encore au fait que le produit des fonctions caractéristiques de A et de B (qui se font par des opérations bitwise) est égal à la fonction caractéristique de A.
    Voici deux évidences:
    Si A est incus dans B, le poids de B est supérieur à celui de A
    Si A est inclus dans B la valeur de B est supérieure à celle de A
    Donc une partie déjà trop lourde ne peut contenir aucune solution. (nouvelle évidence)
     
    Déterminons les 'descendants directs' d'une possibilité comme suit:
    Les descendants directs de P s'obtiennent en ajoutant (si possible) à P un unique objet dont le poids est inférieur ou égal à l'objet le plus léger de P.
    Donnons un exemple:
    Les descendants directs de {0,1,0,0,0}
    sont {0,1,1,0,0} , {0,1,0,1,0} {0,1,0,0,1}
    On fait donc circuler l'unité sur la 'queue de zéros' de P pourvu que cette queue existe.
    Cela dit les descendants de P sont définis récursivement comme étant soit leurs descendants directs, soit les descendants de ces descendants directs.
    En particulier toute possibilité est incluse dans tous ses descendants (mais pas uniquement)
    Tous les descendants de P={0,1,0,0,0} correspondent en fait à toutes les suites binaires de 3 éléments. Parmi celles-ci, il en est une de plus fort poids et de plus forte valeur dans notre cas c'est: {0,1,1,1,1}. Cette possibilité (de poids maximum) se détermine assez facilement à partir de P, et on peut calculer sa valeur Valmax. Si d'aventure cette valeur est inférieure à la borne k définie plus haut, cela signifie qu'il est impossible qu'aucune solution se trouve sur une branche issue de P. 
    Il y a donc deux raisons de ne pas développer une branche correspondant à une possibilité.
    Soit P atteint déjà la poids maximal autorisé pour le sac.
    Soit le Valmax de P est inférieur à la borne k. Dans ce cas on marque le nœud comme 'stérile'
    On développe alors l'arbre 'en largeur'
    Premier niveau:
    Tous les descendants de {0,0,0,0,0}
    soit 10000 01000 00100 00010 00001
    On marque dans ce premier niveau tous les noeuds stériles
    Puis on passe au niveau suivant en développant toutes les feuilles non stériles
    Le processus s'arrête quand on n'obtient plus que des feuilles stériles. Il faut alors choisir celle qui a la plus grande valeur.
    Cet algo se programme certainement assez facilement avec un  LOO (C++, Java, C#).
    Bien que cela puisse grandement faciliter la tâche du programmeur il n'est pas conseillé d'utiliser des structures de données dynamiques même quand le langage en fournit, car les temps d'accès sont élevés, et l'occupation mémoire importante.
     
    Le début d'un code C++ pourrait donc ressembler à cela, mais il n'y a pas de petites économies si les poids restent modestes <256 , il ne faut pas hésiter à les déclarer en unsigned char, idem pour les valeurs
     
    // implémentation de l'ensemble des possibles
    class CPoss
    {
    // données partagées par toutes les instances
    public:
        static int objectsp[5]; // poids des objets en ordre dec
        static int objectsv[5]; // valeurs des objets en ordre dec
    private:
        char fc[5]; // la fonction caractéristique sous forme d'une suite de 0 et de 1
        int  poids; // le poids
        int  valeur; // la valeur
        int valmax; // valeur maximale de tous les descendants
     
    public:
    // constructeurs
    // destructeur
    // autres méthodes pour calculer poids valeur, valmax
     
    };
    // initialisation en dehors de la classe
    int CPoss::objectsp[5]={12,4,2,1,1};
    int CPoss::objectsv[5]={4,10,2,2,1};
     
     
    // Noeuds pour la construction de l'arbre
    // à partir de l'aîné les descendants d'un même parent forment une liste chaînée dans l'arbre
    // ce qui facilite le parcours  en largeur
    class CNode
    {CPoss P;
     CNode * Children; // pointe vers la liste chaînée des enfants
     CNode * Next; // pointe vers le frère suivant de moindre poids
     bool sterile; // déterminé par une méthode spécialisée
     public:
    // constructeurs
    // destructeur
    // autres méthodes pour le marquage
    };
     
    class CTree
    {
    CNode * Root;// le père qui devra pointer sur un noeud contenant la CPoss "00000"
    public:
    // constructeurs
    // destructeur
    // autres méthodes pour le développement et la recherche
    };
    Ce qu'on trouve est plus important que ce qu'on cherche.
    Maths de base pour les nuls (et les autres...)

  10. #10
    Membre expérimenté
    Profil pro
    Inscrit en
    Janvier 2004
    Messages
    192
    Détails du profil
    Informations personnelles :
    Âge : 44
    Localisation : France

    Informations forums :
    Inscription : Janvier 2004
    Messages : 192
    Par défaut
    L'algorithme de programmation dynamique en lien permet d'éviter une énumération arborescente des solutions et fournit ainsi une solution optimale en un temps pseudo-polynomial (O(P*n)), P étant la capacité du sac et n le nombre d'objets.
    A moins d'ajouter un grand nombre de raffinements à une méthode arborescente dans le cas d'un sac-à-dos en 0-1, l'algorithme de prog dyn sera bien plus efficace.
    Si vous voulez chercher plus de références et que vous ne connaissez pas le nom anglosaxon du problème, c'est "Knapsack Problem" (quelle surprise ). Ici, en particulier, 0-1 KP.

  11. #11
    Membre éclairé
    Inscrit en
    Décembre 2005
    Messages
    271
    Détails du profil
    Informations forums :
    Inscription : Décembre 2005
    Messages : 271
    Par défaut
    Mon algo marche bien pour les petits problèmes mais pour les gros ... C est pour ca que je voulais diviser le traitement.

    Mais je vais plutot me tourner vers la programmation dynamique

    Merci !

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. Vends sac a dos Alienware Orion m18x état neuf
    Par Romain.2. dans le forum Petites annonces
    Réponses: 3
    Dernier message: 02/03/2015, 18h38
  2. [PC portable] Bon sac a dos pour un pc portable 13"
    Par Romain.2. dans le forum Ordinateurs
    Réponses: 3
    Dernier message: 26/10/2013, 22h04
  3. [Débutant] probleme de sac a dos
    Par yabo84 dans le forum MATLAB
    Réponses: 1
    Dernier message: 30/11/2010, 15h56
  4. Demande d'info sur optimisation sac-a-dos en prog dynamique
    Par poof65 dans le forum Algorithmes et structures de données
    Réponses: 4
    Dernier message: 13/02/2007, 00h43
  5. probleme du sac a dos (knapsack)
    Par malalll dans le forum Algorithmes et structures de données
    Réponses: 8
    Dernier message: 24/05/2006, 16h52

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo