Algo recouvrir une longueur avec 2 barres de longueur donnée

Résolu
Phil_1857 Messages postés 1883 Date d'inscription   Statut Membre Dernière intervention   -  
Phil_1857 Messages postés 1883 Date d'inscription   Statut Membre Dernière intervention   -

Bonjour,

j'ai un petit algorithme permettant de calculer le nb de barres recouvrant

une longueur donnée, sachant que l'on dispose de 2 longueurs de barres:

250 et 365

On peut couper la dernière barre, ce qui donne une chute

Exemple avec une longueur de 520:

1 barre de 365, une barre de 250, chute = 95

(mesures en cm)

longueur_barre_1 = 365
longueur_barre_2 = 250

longueurs = 552.5, 732.0, 911.5

pour chaque longueur de longueurs
    si longueur est multiple de longueur_barre_1 ou longueur_barre_2
        on choisit longueur_barre_1  ou longueur_barre_2
        pas de chutes

    sinon
        si longueur comprise entre 0 et 250 ou entre 350 et 500
           on pose une 1ere barre longueur_barre_2
        si longueur comprise entre 250 et 365
            on pose une 1ere barre longueur_barre_1
        si longueur > 500
            on choisit la longueur de barre laissant le moins de longueur à recouvrir

    nb_de_barres_maxi = division entiere(longueur/longueur barre)
    reste_a_recouvrir = longueur - longueur barre*nb_de_barres_maxi

    si reste_a_recouvrir non nul
        chute_1 = longueur_barre_1 - reste_a_recouvrir
        chute_2 = longueur_barre_2 - reste_a_recouvrir
        on choisit la longueur de barre laissant la plus petite chute

Ce qui donne:

pour longueur 552.5 : 365,250 chute 62.5
pour longueur 732.0 : 365,365,250 chute 248
pour longueur 911.5 : 365,365,250 chute 68.5

Ce n'est pas satisfaisant: pour la 2eme longueur, on a une chute de 248,

ce qui veut dire que le reste à recouvrir est de 2, on jette une longueur de 2,48m

pour seulement 2 cm à recouvrir

Si quelqu'un avait une idée pour optimiser tout ça 

Merci d'avance


Windows / Edge 119.0.0.0

8 réponses

  1. PierrotLeFou
     

    Je suppose que tu veux aussi avoir le moins de barres possibles?
    Si tu fais nombre = )longueur - 250) / 365 pour le nombre de barres de 365
    Le reste sera (longueur - 250) % 365
    Suivant la valeur du reste, tu choisis une barre de 250 ou 365

    Sinon, si le nombre de barres n'est pas important, le problème revient à optimiser (minimum) l'équation:
    g * 365 + p * 250 - longueur
    Où g est le nombre de barres de 365 et p est le nombre de barres de 250
    Il faut g >= 0 et p >= 0 et que la valeur soit >= 0
    Ce n'est pas l'équation d'une droite?

    0
  2. Phil_1857 Messages postés 1883 Date d'inscription   Statut Membre Dernière intervention   169
     

    Bonsoir Pierrot,

    Merci pour ta réponse

    Effectivement, 365*g + 265*p, ça ressemble à ax + b

    Je vais étudier tout ça ...

    0
  3. yg_be Messages postés 23437 Date d'inscription   Statut Contributeur Dernière intervention   Ambassadeur 1 588
     

    bonjour,

    as-tu écrit que l'objectif était d'avoir le moins de chute possible?

    0
  4. yg_be Messages postés 23437 Date d'inscription   Statut Contributeur Dernière intervention   Ambassadeur 1 588
     

    suggestion

    import sys
    l1 = 365
    l2 = 250
    longueurs = 552.5, 732.0, 911.5,365+250+99
    def brs(lg,lg1,lg2):
        mincht=sys.maxsize
        i1=int(lg//lg1+1)
        i2=int(lg//lg2+1)
        for j1 in range(i1):
            for j2 in range (i2):
                cht=lg-lg1*j1-lg2*j2
                if cht>=0 and cht<mincht:
                        mincht,minn1,minn2=cht,j1,j2
        return (mincht,minn1,minn2)
    for l in longueurs:
        p,n1,n2=brs(l,l1,l2)
        print("Pour une longueur de",l,",",n1,"de ", l1,",",n2,"de",l2, ", perte de",p)
    
    0
    1. yg_be Messages postés 23437 Date d'inscription   Statut Contributeur Dernière intervention   1 588
       

      légèrement optimisé:

      import sys
      l1 = 365
      l2 = 250
      longueurs = 552.5, 732.0, 911.5,365+250+99
      def brs(lg,lg1,lg2):
          mincht=sys.maxsize
          i1=int(lg//lg1+1)
          i2=int(lg//lg2+1)
          x=0
          for j1 in range(i1):
              for j2 in range (i2):
                  x+=1
                  cht=lg-lg1*j1-lg2*j2
                  if cht < 0:
                      break
                  if cht<mincht:
                          mincht,minn1,minn2=cht,j1,j2
          return (mincht,minn1,minn2)
      for l in longueurs:
          p,n1,n2=brs(l,l1,l2)
          print("Pour une longueur de",l,",",n1,"de ", l1,",",n2,"de",l2, ", perte de",p)
      
      0
  5. Vous n’avez pas trouvé la réponse que vous recherchez ?

    Posez votre question
  6. yg_be Messages postés 23437 Date d'inscription   Statut Contributeur Dernière intervention   Ambassadeur 1 588
     

    En utilisant une fonction python d'optimisation linéaire en nombres entiers:

    import cvxopt.glpk
    import numpy
    lg1,lg2 = 365, 250
    longueurs = 552.5, 732.0, 911.5,365+250+99,99*lg1+97*lg2+79
    def brs(lg,l1,l2):
        # minimiser -l1*g-l2*p
        c=numpy.array([-l1,-l2],dtype=float)
        #contraintes
        #      -g <= 0
        #      -p <= 0
        #      l1*g+l2*p <= lg
        G=cvxopt.matrix(numpy.array([[-1,0],[0,-1],[l1,l2]],dtype=float))
        h=cvxopt.matrix(numpy.array([0,0,lg],dtype=float))
        I=set(range(2))
        B=set()
        A=cvxopt.matrix(1., (0,2))
        b=cvxopt.matrix(1., (0,1))
        (status,x)=cvxopt.glpk.ilp(c,G,h,A,b,I,B,options={'show_progress': False,'msg_lev': 'GLP_MSG_OFF'})
        return(x)
    for l in longueurs:
        (n1,n2)=brs(l,lg1,lg2)
        p=l-n1*lg1-n2*lg2
        print("Pour une longueur de",l,",",n1,"de ", lg1,",",n2,"de",lg2, ", perte de",p)
    
    0
  7. Phil_1857 Messages postés 1883 Date d'inscription   Statut Membre Dernière intervention   169
     

    Bonjour,

    Oui, il faut optimiser le nb de barres et éviter les trucs comme celui

    que je décris: couper une barre pour combler 2cm (récupérer une chute

    pour refaire la ligne ?)

    Merci pour les exemples de code, je vais regarder ça ...

    Ah ok :

    Je me suis peut-être mal expliqué

    Pour 552.5, par exemple, ton code donne 2 barres de 250, donc 500cm

    couverts, et il reste à recouvrir 52.5

    En fait, je veux plutôt recouvrir toute la longueur, quitte à laisser une chute:

    1 barre de 365, 1 barre de 250, ce qui donne 615cm, donc couper la

    2eme barre à la longueur, ce qui donne une chute de 62.5cm

    0
    1. yg_be Messages postés 23437 Date d'inscription   Statut Contributeur Dernière intervention   1 588
       

      tu veux minimiser le nombre de barres, ou minimiser la longueur de la chute?

      0
  8. yg_be Messages postés 23437 Date d'inscription   Statut Contributeur Dernière intervention   Ambassadeur 1 588
     

    si tu veux minimiser le nombre de barres:

    import cvxopt.glpk
    import numpy
    lg1,lg2 = 365, 250
    longueurs = 552.5, 732.0, 911.5,365+250+99,99*lg1+97*lg2+79,123,97*lg1+99*lg2+79,97*lg1+99*lg2+179
    def brs(lg,l1,l2):
        # minimiser g+p
        c=numpy.array([1,1],dtype=float)
        #contraintes
        #      -g <= 0
        #      -p <= 0
        #      -l1*g-l2*p <= -lg
        G=cvxopt.matrix(numpy.array([[-1,0],[0,-1],[-l1,-l2]],dtype=float))
        h=cvxopt.matrix(numpy.array([0,0,-lg],dtype=float))
        I=set(range(2))
        B=set()
        A=cvxopt.matrix(1., (0,2))
        b=cvxopt.matrix(1., (0,1))
        (status,x)=cvxopt.glpk.ilp(c,G,h,A,b,I,B,options={'msg_lev': 'GLP_MSG_OFF'})
        return(x)
    for l in longueurs:
        (n1,n2)=brs(l,lg1,lg2)
        ch=l-n1*lg1-n2*lg2
        print("Pour une longueur de",l,",",n1,"de ", lg1,",",n2,"de",lg2, ", chute de",-ch)
    
    
    0
    1. yg_be Messages postés 23437 Date d'inscription   Statut Contributeur Dernière intervention   1 588
       

      si tu veux minimiser la longueur de la chute:

      import cvxopt.glpk
      import numpy
      lg1,lg2 = 365, 250
      longueurs = 552.5, 732.0, 911.5,365+250+99,99*lg1+97*lg2+79,123,97*lg1+99*lg2+79,97*lg1+99*lg2+179
      def brs(lg,l1,l2):
          # minimiser  l1*g+l2*p
          c=numpy.array([lg1,lg2],dtype=float)
          #contraintes
          #      -g <= 0
          #      -p <= 0
          #      -l1*g-l2*p <= -lg
          G=cvxopt.matrix(numpy.array([[-1,0],[0,-1],[-l1,-l2]],dtype=float))
          h=cvxopt.matrix(numpy.array([0,0,-lg],dtype=float))
          I=set(range(2))
          B=set()
          A=cvxopt.matrix(1., (0,2))
          b=cvxopt.matrix(1., (0,1))
          (status,x)=cvxopt.glpk.ilp(c,G,h,A,b,I,B,options={'msg_lev': 'GLP_MSG_OFF'})
          return(x)
      for l in longueurs:
          (n1,n2)=brs(l,lg1,lg2)
          ch=l-n1*lg1-n2*lg2
          print("Pour une longueur de",l,",",n1,"de ", lg1,",",n2,"de",lg2, ", chute de",-ch)
      
      
      
      0
  9. Phil_1857 Messages postés 1883 Date d'inscription   Statut Membre Dernière intervention   169
     

    Ah ok, merci

    D'abord, je vais me familiariser avec numpy et cvxopt  :-) :-)

    0