Algorithme pour le pourcentage sans connaître le nombre total

17

Supposons qu'il existe des nlignes pour une hotline.

Chaque fois qu'un client appelle la hotline, l'appel est renvoyé vers l'une des nlignes. Et je veux attribuer un pourcentage d'appel à chacune des n lignes. Supposons qu'il y ait deux lignes et qu'une ligne soit affectée à 60% et l'autre à 40%, le nombre total d'appels est de 10, de sorte que la première ligne recevrait 6 appels et la seconde 4 appels.

Je connais le pourcentage d'appels vers chaque ligne à l'avance, mais le problème est que je ne connais pas le nombre d'appels qui seraient reçus en une journée.

Comment puis-je répartir le nombre d'appels sans connaître le nombre total d'appels?

akku
la source
2
Après que la ligne 1 a reçu 6 appels, passez à la ligne 2 4 appels. Autrement dit, ne vous souciez pas du nombre total réel, faites attention à la distribution sur la "période" (10, dans ce cas) que vous connaissez. Évidemment, vous pouvez faire des choses comme des lignes alternatives, sauf la dernière valeur, il n'y a donc pas non plus d'attente stricte. S'il existe une sorte de file d'attente, effectuez le pourcentage en fonction des lignes actuelles de la file d'attente.
Clockwork-Muse
qu'est-ce que "astérisque" et "DID"?
moucher
@ Clockwork-Muse: Je suggérerais d'arrondir les entiers ici au lieu de maintenir la distribution 6-4. Sinon, votre distribution sera désactivée, sauf si vous savez que vous avez un multiple exact de 10 appels. Par exemple, si 6 appels au total entrent, votre approche suggérée les attribuerait tous à la ligne A; alors qu'une approche plus correcte serait 4 à A et 2 à B (attribués dans l'ordre ABAABA si vous arrondissez les totaux d'affectation pour chaque ligne)
Flater

Réponses:

26

Faites un peu de comptabilité sur les appels déjà pris et calculez leur répartition sur les n lignes. Cela vous donne n pourcentages (votre distribution déjà atteinte), qui peuvent être comparés aux n pourcentages que vous souhaitez atteindre. Chaque fois qu'un nouvel appel arrive, affectez cet appel à la ligne avec l'écart le plus élevé par rapport à la valeur cible (notez que tant que vous ne frappez pas exactement la distribution donnée, il y a toujours une ligne qui a jusqu'à présent trop peu d'appels, par rapport à la distribution cible).

Par exemple: après avoir attribué le premier appel à la ligne 1:

 total calls line1      total calls line2    perc.line 1    perc. line 2
 1                      0                    100%             0% 
                                             *above 60%      *below 40% <- next call to 2
 1                      1                    50%             50% 
                                             * below 60%:    *above40% next to line1
 2                      1                    66%             33%
                                             *above 60%      *below 40% <- next to line 2
 2                      2                    50%             50% 
                                             * below 60%:    *above40% next to line1
 3                      2                    60%             40% 
                                             * both hit the mark: next call arbitrary
 4                      2                    66%             33%
                                             *above 60%      *below 40% <- next to line 2
 4                      3                    57.1%             42.85%
                                             *below 60%      *above 40% <- next to line 1

...

EDIT: Cette approche pourrait être encore améliorée en n'utilisant pas la différence absolue, mais en choisissant la ligne qui minimise la somme des carrés de tous les écarts. Cela vous donnerait également un meilleur résultat si vous atteignez exactement les valeurs cibles.

Doc Brown
la source
2
Vous souhaiterez peut-être changer cela "tant que" en une référence plus explicite "utilisez un autre bris d'égalité", FWIW.
DougM
@DougM: voir ma modification.
Doc Brown
5
  • Supposons que le nombre de travailleurs soit inférieur à 100
  • Créez une gamme de travailleurs d'une capacité de 100
  • Mettez dans ce tableau un travailleur un nombre de fois égal au pourcentage d'appels qu'il devrait recevoir, par exemple si le travailleur1 devrait recevoir 30% de tous les appels, puis placez-le dans les positions 0 à 29 du tableau.
  • À la fin, chaque position du tableau doit être utilisée et les employés doivent apparaître dans le tableau autant de fois que le pourcentage d'appels qu'ils devraient recevoir.
  • Dans une boucle, générez un nombre aléatoire compris entre 0 et 99 et affectez l'appel entrant au travailleur dans cette position du tableau. Si le travailleur est occupé, répétez.
  • De cette façon, par pure probabilité, les appels seront distribués comme souhaité
  • Dans mon exemple, travailleur1 a 30/100 de chances d'être choisi à une itération donnée.
Tulains Córdova
la source
4

Je suis d'accord avec la solution de @ DocBrown. Le placer dans une forme d'algorithme:

for each incoming call:
    sort lines ascending by delta* (see footnote below)

    // first element in array gets the call 
    increase number of calls for first element by 1
  • Delta est déterminé par le pourcentage réel moins le pourcentage attendu d'une ligne. De cette façon, ceux qui ont le plus grand delta négatif sont ceux qui ont le plus besoin d'un appel pour se conformer au pourcentage attendu.

    Par exemple, dans le cas où les pourcentages attendus pour les lignes 1 et 2 sont respectivement de 60% et 40%, et leurs pourcentages réels sont de 50% et 50%, vous verriez la ligne de commande 1 suivie de la ligne 2, car -10 % est inférieur à 10%. Par conséquent, la ligne 1 recevrait l'appel.

    Je recommande fortement d'utiliser le tri par insertion car il fonctionne mieux lorsque le tableau est déjà principalement trié.

De plus, comme optimisation mineure, si vous gardez une trace du nombre total d'appels jusqu'à présent, plutôt que d'avoir à calculer le pourcentage réel de chaque ligne, vous pouvez simplement calculer le nombre total d'appels pour cette ligne moins le pourcentage attendu pour cette ligne. ligne multipliée par le nombre total d'appels (delta = t_i - p_i * T). Dans ce cas, le delta est simplement le nombre négatif d'appels pour atteindre le pourcentage attendu.

J'espère que cela clarifie tout autre doute.

Neil
la source
merci @Neil, vous m'avez vraiment aidé, mais quand les deux ont atteint la cible, alors quelle ligne dois-je appeler, y a-t-il des critères pour cela?
akku
@akku Avec mon algorithme, vous prenez simplement le premier toujours après le tri, ce qui signifie que l'algorithme s'en fiche. Si vous avez un autre critère à appliquer, vous devez le faire peser en conséquence lorsque vous le triez. En d'autres termes, si le numéro de ligne était important, alors vous devriez prendre le delta, multiplier par le nombre total de lignes, puis ajouter le numéro de ligne actuel. Cela favorise des numéros de ligne plus élevés, en supposant que tout le reste est égal.
Neil
@Neil: votre réponse est bonne, mais chaque fois que je vois quelqu'un suggérer de trier un tableau complètement juste pour trouver la valeur minimale, je pense "Great Scott, est-ce vraiment nécessaire?"
Doc Brown
@DocBrown O(n)est ce que vous pouvez vous attendre à trier une liste déjà triée avec le tri par insertion et O(n)c'est ce que vous devez utiliser pour trouver la plus petite valeur. Je suppose simplement que je l'ai trié.
Neil
@Neil: simplement parce que deux algorithmes sont tous les deux O (n), ils ne sont pas aussi simples (ou aussi rapides).
Doc Brown
2

Hypothèses énoncées dans le PO

  1. Le nombre de lignes, n, est connu et;
  2. Le% de chaque ligne est connu

Conception d'algorithmes

  1. Définissez chaque ligne par son%

  2. Trier chaque ligne par sa position à l'écart de 0 définie comme (% actuel de travailleurs -% de travailleurs affectés) ou par assignation aléatoire si toutes les lignes = 0

  3. Transférer chaque appel vers la plus grande ligne à partir de 0

Exemple: 3 lignes avec un% de 20, 30 et 50 respectivement. Au point x dans le temps, 1 personne appelle et puisque chaque ligne est à 0 de 0, elle est assignée au hasard - disons à la ligne 2 qui devrait contenir 30% de tous les appels. Étant donné que la ligne 2 devrait contenir 30% de tous les appels et détient désormais 100% de tous les appels, sa position à partir de 0 augmente. L'appelant suivant serait maintenant affecté à la ligne 1 ou à la ligne 3, etc. jusqu'à l'équilibre (0) et donc la boucle se répète.

implacable
la source
0

Il s'agit d'une solution naïve qui ne suppose rien mais permettrait une distribution basée sur un pourcentage. Cette solution pourrait être améliorée de nombreuses façons, mais c'est l'essentiel. Je ne sais pas si c'est ce que vous cherchez, mais cela vous donnerait une vraie distribution.

code pseudo ...

int running_total_of_calls = 0

//This is hard coded for clarity. You'd most likely want to dynamically populate this array depending and probably distribute the work by alternating workers. Notice how "worker1" appears 6 out of 10 times in the array.
string[] worker = new string[10]
workers[0] = "worker1"
workers[1] = "worker1"
workers[2] = "worker1"
workers[3] = "worker1"
workers[4] = "worker1"
workers[5] = "worker1"
workers[6] = "worker2"
workers[7] = "worker2"
workers[8] = "worker2"
workers[9] = "worker2"

while(1) //run forever
    //This is where the distribution occurs. 
    //first iteration: 0 modulus 10 = 0. 
    //second: 1 modulus 10 = 1
    //third: 2 modulus 10 = 2
    //...
    //10th: 10 modulus 10 = 0
    //11th: 11 modulus 10 = 1 
    //12th: 12 modulus 10 = 2
    //...
    int assigned_number = running_total_of_calls % workers.Count //count of workers array
    string assigned_worker = workers[assigned_number]
    do_work(assigned_worker)
    running_total_of_calls = ++running_total_of_calls
Odnxe
la source