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

Résolu
Phil_1857 Messages postés 1883 Date d'inscription lundi 23 mars 2020 Statut Membre Dernière intervention 28 février 2024 - Modifié le 11 nov. 2023 à 11:58
Phil_1857 Messages postés 1883 Date d'inscription lundi 23 mars 2020 Statut Membre Dernière intervention 28 février 2024 - 12 nov. 2023 à 12:15

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

A voir également:

8 réponses

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
Phil_1857 Messages postés 1883 Date d'inscription lundi 23 mars 2020 Statut Membre Dernière intervention 28 février 2024 178
Modifié le 11 nov. 2023 à 19:12

Bonsoir Pierrot,

Merci pour ta réponse

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

Je vais étudier tout ça ...

0
yg_be Messages postés 22696 Date d'inscription lundi 9 juin 2008 Statut Contributeur Dernière intervention 17 avril 2024 1 471
11 nov. 2023 à 19:51

bonjour,

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

0
yg_be Messages postés 22696 Date d'inscription lundi 9 juin 2008 Statut Contributeur Dernière intervention 17 avril 2024 1 471
11 nov. 2023 à 20:51

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
yg_be Messages postés 22696 Date d'inscription lundi 9 juin 2008 Statut Contributeur Dernière intervention 17 avril 2024 1 471
Modifié le 12 nov. 2023 à 08:49

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

Vous n’avez pas trouvé la réponse que vous recherchez ?

Posez votre question
yg_be Messages postés 22696 Date d'inscription lundi 9 juin 2008 Statut Contributeur Dernière intervention 17 avril 2024 1 471
Modifié le 12 nov. 2023 à 10:31

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
Phil_1857 Messages postés 1883 Date d'inscription lundi 23 mars 2020 Statut Membre Dernière intervention 28 février 2024 178
Modifié le 12 nov. 2023 à 10:59

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
yg_be Messages postés 22696 Date d'inscription lundi 9 juin 2008 Statut Contributeur Dernière intervention 17 avril 2024 1 471
12 nov. 2023 à 11:45

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

0
yg_be Messages postés 22696 Date d'inscription lundi 9 juin 2008 Statut Contributeur Dernière intervention 17 avril 2024 1 471
12 nov. 2023 à 11:49

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
yg_be Messages postés 22696 Date d'inscription lundi 9 juin 2008 Statut Contributeur Dernière intervention 17 avril 2024 1 471
12 nov. 2023 à 11:54

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
Phil_1857 Messages postés 1883 Date d'inscription lundi 23 mars 2020 Statut Membre Dernière intervention 28 février 2024 178
12 nov. 2023 à 12:15

Ah ok, merci

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

0