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 :

Algorithme de réapprovisionnement de pharmacie


Sujet :

Algorithmes et structures de données

  1. #1
    Membre régulier
    Algorithme de réapprovisionnement de pharmacie
    Bonjour,

    je bute depuis plusieurs semaines sur un algorithme permettant d'éditer une liste de médicaments à expédier.

    2 types de pharmacie :
    - pharmacie site
    - pharmacie pays qui réapprovisionne les pharmacies site du pays

    2 catégories de médicaments à réapprovisionner :
    - placebo (P)
    - médicament de l'étude (M)

    objectif :
    - permettre à une pharmacie pays d'éditer une liste de médicaments à expédier dans un site en se basant sur (1) un seuil défini pour le site dans une table de paramétrages et (2) les stocks actuellement disponibles sur le site

    contraintes :
    - toujours respecter l'équilibre 50/50 placebo/médicament de l'étude
    - les pharmacies sont en 'aveugle' -> commande des quantité globales (médicament + placebo)
    - on défini des quantités à commander calculées comme valeurs par défaut mais l'utilisateur peut modifier cette valeur

    j'ai essayé de définir les différents cas de figures mais je m'y perd
    une des difficultés est le fait que l'utilisateur est en aveugle et peut modifier la quantité calculée par défaut (il commande une quantité globale)


    ci-dessous, la fonction que j'ai commencé à écrire

    Code Python :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
     
    # site : site a reapprovisionner
    # pays : pays du site à réapprovisionner
    # quantite : quantite demandee (peut être égale à la valeur par défaut calculée à partir des stocks disponibles sur site et du seuil de confort)
    def liste_medicaments_a_expedier(pays,site,quantite):
     
        # liste des médicaments à retourner
        medicaments = []
     
        # seuil du site
        seuil = Parametrage.objects.get(asp_par_loc = site).asp_par_con
     
        # Medicaments disponibles sur le site a réapprovisionner
        medicament_disponible_site = [m.med_num for m in Medicament.objects.filter(Q(med_dru = 1) & Q(med_sit = site) & Q(med_eta=1))]
        placebo_disponible_site = [m.med_num for m in Medicament.objects.filter(Q(med_dru = 2) & Q(med_sit = site) & Q(med_eta=1))]
     
        # Medicaments disponibles dans le pays du site a réapprovisionner
        medicament_disponible_pays = [m.med_num for m in Medicament.objects.filter(Q(med_dru = 1) & Q(med_sit = pays) & Q(med_eta=1))]
        placebo_disponible_pays = [m.med_num for m in Medicament.objects.filter(Q(med_dru = 2) & Q(med_sit = pays) & Q(med_eta=1))]
     
     
        # quantités à commander calculées en fonction du seuil
        quantite_medicament_a_commander = seuil - len(medicament_disponible_site)
        quantite_placebo_a_commander = seuil - len(placebo_disponible_site)
     
        # si les stocks sont suffisants
        if quantite_medicament_a_commander<=len(medicament_disponible_pays) and quantite_placebo_a_commander<=len(placebo_disponible_pays):
            medicaments = medicament_disponible_pays[:int(quantite_medicament_a_commander)] + placebo_disponible_pays[:int(quantite_placebo_a_commander)]
        # si les stocks sont insuffisants -> nouveau calcul des quantités à expédier
        else:
            if len(medicament_disponible_pays) < len(placebo_disponible_pays):
                quantite_equilibre = len(medicament_disponible_pays) + len(medicament_disponible_site)
     
            elif len(medicament_disponible_pays) > len(placebo_disponible_pays):
                quantite_equilibre = len(placebo_disponible_pays) + len(placebo_disponible_site)
     
            else:
                quantite_equilibre = len(placebo_disponible_pays) + min(len(medicament_disponible_site),len(placebo_disponible_site))
            medicaments = medicament_disponible_pays[:int(quantite_equilibre - len(medicament_disponible_site))] + placebo_disponible_pays[:int(quantite_equilibre - len(placebo_disponible_site))]
     
     
        return medicaments

  2. #2
    Expert éminent sénior
    Bonjour

    Pourquoi une simple division par 2 n'est-elle pas suffisante ?

    Exemple : Une pharmacie a 400 médocs. Il lui en faut 600. Par défaut, elle nécessite 200. Mais elle demande 400. Donc la pharmacie pays lui envoie 200 placébos (P) et 200 médicaments (M). J'ai juste divisé la demande par 2 pour trouver les quantités. Et on a bien 50%-50%.

    Pourquoi ce raisonnement simple ne convient pas ?
    Cette réponse vous apporte quelque chose ? Cliquez sur en bas à droite du message.

  3. #3
    Membre régulier
    bonjour,

    parce qu'il faut tenir compte des quantités de chaque catégorie de médicaments sur site pour conserver le 50/50

    en divisant par 2, on fait l'hypothèse que la répartition sur site avant réapprovisionnement est de 50/50 ce qui ne sera pas forcément le cas

  4. #4
    Expert éminent sénior
    D'accord mais dis-en plus. La pharmacie pays connaît-elle la répartition réelle d'une des pharmacies ? Si oui, il suffit de compléter l'écart et diviser le reste par deux. Sinon comment veux-tu obtenir un résultat alors que ni la pharmacie locale, ni la pharmacie pays n'ont l'information ?
    Cette réponse vous apporte quelque chose ? Cliquez sur en bas à droite du message.

  5. #5
    Membre régulier
    aucune des pharmacies (pays ou site) ne connait la répartition des médicaments, ils sont en aveugle

    par contre en base, on a bien sûr les stocks de chaque catégorie de médicaments dans chacune des pharmacies

    ce que l'on veut c'est 'aider' les pharmacies pays dans leur réapprovisionnement à partir d'un seuil et en essayant de garantir une répartition 50/50

  6. #6
    Expert éminent sénior
    Donc tu as la solution.

    Je reprends l'exemple précédent. La pharmacie a 300 médocs et 100 placebos, sans le savoir. Elle sait juste qu'elle a 400. Elle commande 400 (pour avoir plus de 600 comme précédemment). Et la base de données complète le différentiel de 200 puis divise le reste (200) par 2. Elle conseillera donc d'envoyer 300 placebos P et 100 médicaments M; pour un total de 800 médicaments dont 400P et 400M, 50%-50%.

    Si la quantité demandée est trop faible pour combler l'écart, on n'envoie que le produit déficitaire.
    Si on tombe sur un nombre impair, on garde en mémoire si c'est P ou M qui est en excédant pour une unité. La fois suivante, ce sera le contraire, pour retomber sur la parité.
    Cette réponse vous apporte quelque chose ? Cliquez sur en bas à droite du message.

  7. #7
    Membre expérimenté
    Dans une étude de ce genre, chaque patient reçoit pendant toute la durée le même produit ( P ou M). Et la pharmacie de pays ne doit pas le savoir. Chaque boite au départ doit être adressée à un patient précis.
    Ce qui s'énonce clairement se conçoit bien ( Le hautbois)

  8. #8
    Membre régulier
    exactement

    ci-dessous l'algo le 'moins pire' pour le moment

    Code Python :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
    # site : site a reapprovisionner
    # pays : pays du site à réapprovisionner
    # quantite : quantite demandee (peut être égale à la valeur par défaut calculée à partir des stocks disponibles sur site et du seuil de confort)
    def liste_medicaments_a_expedier(pays,site,quantite):
     
     
        # liste des médicaments à retourner
        medicaments = []
     
        # seuil de confort
        seuil_confort = Parametrage.objects.get(asp_par_loc = site).asp_par_con
     
        # Medicaments disponibles sur le site a réapprovisionner
        medicament_disponible_site = [m.med_num for m in Medicament.objects.filter(Q(med_dru = 1) & Q(med_sit = site) & Q(med_eta=1))]
        placebo_disponible_site = [m.med_num for m in Medicament.objects.filter(Q(med_dru = 2) & Q(med_sit = site) & Q(med_eta=1))]
     
     
        # Medicaments disponibles dans le pays du site a réapprovisionner
        medicament_disponible_pays = [m.med_num for m in Medicament.objects.filter(Q(med_dru = 1) & Q(med_sit = pays) & Q(med_eta=1))]
        placebo_disponible_pays = [m.med_num for m in Medicament.objects.filter(Q(med_dru = 2) & Q(med_sit = pays) & Q(med_eta=1))]
     
     
        # quantités à commander calculées en fonction du seuil de confort
        quantite_medicament_a_commander = seuil_confort - len(medicament_disponible_site)
        quantite_placebo_a_commander = seuil_confort - len(placebo_disponible_site)
     
     
     
        # si les stocks sont suffisants
        if quantite_medicament_a_commander<=len(medicament_disponible_pays) and quantite_placebo_a_commander<=len(placebo_disponible_pays):
     
            medicaments = medicament_disponible_pays[:int(quantite_medicament_a_commander)] + placebo_disponible_pays[:int(quantite_placebo_a_commander)]
     
        # si les stocks sont insuffisants -> nouveau calcul des quantités à expédier
        else:
     
            if len(medicament_disponible_site) > len(placebo_disponible_site):
     
                if len(medicament_disponible_pays) > len(placebo_disponible_pays):
     
                    quantite_medicament = (len(placebo_disponible_pays) + len(placebo_disponible_site)) - len(medicament_disponible_site)
                    if quantite_medicament < 0:
                        quantite_medicament = 0
                    medicaments = medicament_disponible_pays[:int(quantite_medicament)] + placebo_disponible_pays
     
                if len(medicament_disponible_pays) <= len(placebo_disponible_pays):
     
                    quantite_placebo = (len(medicament_disponible_pays) + len(medicament_disponible_site)) - len(placebo_disponible_site)
                    if quantite_placebo < 0:
                        quantite_placebo = 0
     
                    medicaments = medicament_disponible_pays + placebo_disponible_pays[:int(quantite_placebo)]
     
            if len(medicament_disponible_site) == len(placebo_disponible_site):
     
                quantite_medicament = quantite_placebo = min(len(medicament_disponible_pays),len(placebo_disponible_pays))
                if quantite_medicament < 0:
                    quantite_medicament = 0
                    quantite_placebo = 0
     
                medicaments = medicament_disponible_pays[:int(quantite_medicament)] + placebo_disponible_pays[:int(quantite_placebo)]
     
            if len(medicament_disponible_site) < len(placebo_disponible_site):
     
                if len(medicament_disponible_pays) <= len(placebo_disponible_pays):
     
                    if quantite_placebo < 0:
                        quantite_placebo = 0
                    print('quantite_placebo',quantite_placebo)
                    medicaments = medicament_disponible_pays + placebo_disponible_pays[:int(quantite_placebo)]
     
     
                if len(medicament_disponible_pays) > len(placebo_disponible_pays):
     
                    quantite_medicament = (len(placebo_disponible_pays) + len(placebo_disponible_site)) - len(medicament_disponible_site)
                    if quantite_medicament < 0:
                        quantite_medicament = 0
     
                    medicaments = medicament_disponible_pays[:int(quantite_medicament)] + placebo_disponible_pays             
     
     
        return medicaments

  9. #9
    Expert confirmé
    salut

    ton seuil doit etre multiplier par le ratio correspondant au type de produit
    Code :Sélectionner tout -Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
     
      SEUIL  = DonneSeuil(PAYS,SITE);
      DISPOM = GetMedocDispo(PAYS,SITE,M);
      DISPOP = GetMedocDispo(PAYS,SITE,P);
     
      MDISPOPAYS = GetMedocDispo(PAYS,M);
      PDISPOPAYS = GetMedocDispo(PAYS,P);
     
      // on calcul les different seuil a trouver
      SEUILM =  SEUIL*GetPourCent(PAYS,SITE,M)
      SEUILP =  SEUIL*GetPourCent(PAYS,SITE,P)


    une fois le seuil théorique et sa répartition définie tu dois chercher d'autre dérive
    Code :Sélectionner tout -Visualiser dans une fenêtre à part
    1
    2
    3
     
      ECM  = SEUILM -  DISPOM
      ECP  = SEUILP -  DISPOP


    le cas le plus simple
    les element a chercher sont positif et les stock sont supérieur
    Code :Sélectionner tout -Visualiser dans une fenêtre à part
    1
    2
    IF DISPOPAYSM  >  ECM and  DISPOPAYSP  >  ECP  and  ECP>0 and  ECM > 0 
       MEDICAMENTS = GETSTOCK(ECM,M) +   GETSTOCK(ECP,P)


    ensuite cela se complique il faut trouver le plus grand dénominateur commun pour caque type
    il te faut donc trouver le nombre d’éléments pour compenser le déséquilibre

    Code :Sélectionner tout -Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
     
    CSP  =0
    CSM = 0
    if ECM < 0  
      CSP = (ABS(ECM)/GetPourCent(PAYS,SITE,M))* GetPourCent(PAYS,SITE,P)
     
    if ECP < 0  
      CSM = (ABS(ECP)/GetPourCent(PAYS,SITE,P))* GetPourCent(PAYS,SITE,M)


    une fois obtenu tes valeurs de compensation
    il faut trouver le seuil équilibre théorique pour chaque type

    Code :Sélectionner tout -Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
     
       ...
      SEUILEQUILIBREM  =  MDISPOPAYS/GetPourCent(PAYS,SITE,M)
       ...
      SEUILEQUILIBREP  =  PDISPOPAY/GetPourCent(PAYS,SITE,P)
       ...
      SEUILEQUILIBRE = Min(SEUILEQUILIBREP,SEUILEQUILIBREP)
      SEUILEQUILIBRE = Min(SEUILEQUILIBREP,SEUIL)


    et enfin

    Code :Sélectionner tout -Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
     
      RCOMM = SEUILEQUILIBRE * GetPourCent(PAYS,SITE,M)
      RCOMP = SEUILEQUILIBRE - SEUILM
     
      MEDICAMENTS = GETSTOCK(RCOMM,M) +   GETSTOCK(RCOMP,P)
    Nous souhaitons la vérité et nous trouvons qu'incertitude. [...]
    Nous sommes incapables de ne pas souhaiter la vérité et le bonheur, et sommes incapables ni de certitude ni de bonheur.
    Blaise Pascal
    PS : n'oubliez pas le tag

  10. #10
    Membre régulier
    merci pour ta réponse
    je confirme que je suis un "brêle" en algo et j'ai pas encore tout compris à ton algo
    je vais essayer de décortiquer ton algo...


    // on calcul les different seuil a trouver
    SEUILM = SEUIL*GetPourCent(PAYS,SITE,M)
    SEUILP = SEUIL*GetPourCent(PAYS,SITE,P)
    que retourne ta fonction GetPourCent ?

  11. #11
    Expert confirmé
    salut

    le pourcentage de médicament(M) ou de placebo(P)

    en ce moment c'est 50% mais qui te dis que dans l'avenir tu ne voudras pas un ration de 25%-75%

    j'ai essayé d’être le plus empirique possible
    Nous souhaitons la vérité et nous trouvons qu'incertitude. [...]
    Nous sommes incapables de ne pas souhaiter la vérité et le bonheur, et sommes incapables ni de certitude ni de bonheur.
    Blaise Pascal
    PS : n'oubliez pas le tag

  12. #12
    Membre régulier
    Salut

    Ok, je comprends et c'est ce que j'imaginais et c'est une bonne pratique

    mais dans mon cas, il s'agit d'un essai randomisé donc on ne voudra jamais changer l'équilibre 50/50
    au contraire, en cours d'essai on essaie de maintenir au mieux cet équilibre à la pharmacie pour le bon déroulement de l'essai

  13. #13
    Expert confirmé
    Salut,

    je comprend mais ce qui est bon pour le cas général est aussi bon pour le cas particulier qui nous intéresse
    Nous souhaitons la vérité et nous trouvons qu'incertitude. [...]
    Nous sommes incapables de ne pas souhaiter la vérité et le bonheur, et sommes incapables ni de certitude ni de bonheur.
    Blaise Pascal
    PS : n'oubliez pas le tag

  14. #14
    Expert éminent sénior
    Soit x le nombre de médicaments M en pharmacie (donné)
    y le nombre de médicaments P en pharmacie (donné)
    z le nombre de médicaments M ajoutés
    w le nombre de médicaments P ajoutés
    k le nombre de médicaments commandés. (donné)
    r le ratio final de médicaments M parmi les médicaments. (donné)

    z + w = k => z = k - w

    ( x + z + y + w ) * r = x + z
    xr - x +zr - z + yr + wr = 0
    xr - x + kr - wr - k + w + yr + wr = 0 ( on a remplacé z)
    w = x - xr - kr + k - yr
    z = k - x + xr + kr - k + yr

    z = r ( x + y + k ) - x

    Si je reprends mon exemple, (x,y,k,r) = (300,100,400,1/2), on obtient z = 100 et w = 300. Ça semble être juste.
    Cette réponse vous apporte quelque chose ? Cliquez sur en bas à droite du message.