Algoritmo per percentuale senza conoscere il numero totale


17

Supponiamo che ci siano nlinee per una hotline.

Ogni volta che un cliente chiama la hotline, la chiamata viene inoltrata a una delle nlinee. E voglio assegnare la percentuale di chiamata a ciascuna delle n linee. Supponiamo che ci siano due linee e una linea sia assegnata al 60% e l'altra al 40%, il numero totale di chiamate è 10, quindi la prima linea riceverà 6 chiamate e la seconda riceverà 4 chiamate.

Conosco in anticipo la percentuale di chiamate verso ciascuna linea, ma il problema è che non conosco il numero di chiamate che verrebbero ricevute in un giorno.

Come posso distribuire il numero di chiamate senza conoscere il totale delle chiamate?


2
Dopo che la linea 1 riceve 6 chiamate, assegnare alla linea 2 4 chiamate. Cioè, non preoccuparti del conteggio totale effettivo, preoccupati della distribuzione nel "periodo" (10, in questo caso) che conosci. Ovviamente puoi fare cose come linee alternative tranne l'ultimo valore, quindi non è nemmeno necessaria un'attesa rigorosa. Se esiste una sorta di coda, esegui la percentuale in base alle righe correnti nella coda.
Clockwork-Muse,

che cos'è "asterisco" e "DID"?
moscerino il

@ Clockwork-Muse: suggerirei di arrotondare qui gli interi invece di mantenere la distribuzione 6-4. Altrimenti la tua distribuzione sarà disattivata se non sai di avere un multiplo esatto di 10 chiamate. Ad esempio, se arrivano 6 chiamate totali, l'approccio suggerito le assegnerebbe tutte alla linea A; considerando che un approccio più corretto sarebbe da 4 a A e da 2 a B (assegnato nell'ordine ABAABA se si arrotondano i totali di assegnazione di numeri interi per ogni riga)
Flater

Risposte:


26

Fai un po 'di contabilità sulle chiamate già prese e calcola la loro distribuzione sulle n righe. Questo ti dà n valori percentuali (la tua distribuzione già raggiunta), che possono essere confrontati con le n percentuali che vuoi raggiungere. Ogni volta che arriva una nuova chiamata, assegna quella chiamata alla linea con la deviazione più alta dal valore target (nota che fino a quando non colpisci esattamente la data distribuzione, c'è sempre una linea che ha troppe poche chiamate finora, rispetto alla distribuzione target).

Ad esempio: dopo aver assegnato la prima chiamata alla linea 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: questo approccio potrebbe essere ulteriormente migliorato non usando la differenza assoluta, ma scegliendo la linea che minimizza la somma dei quadrati di tutte le deviazioni. Ciò darebbe anche un risultato migliore nel caso in cui si raggiungano esattamente i valori target.


2
È possibile che si desideri modificare il riferimento "Fintanto che" in modo più esplicito "utilizzare un diverso tiebreaker", FWIW.
DougM,

@DougM: vedi la mia modifica.
Doc Brown,

5
  • Supponiamo che il numero di lavoratori sia inferiore a 100
  • Crea una serie di lavoratori con una capacità di 100
  • Inserire un array in un lavoratore un numero di volte uguale alla percentuale di chiamate che dovrebbe ricevere, ad esempio se worker1 dovesse ricevere il 30% di tutte le chiamate, quindi posizionarlo nelle posizioni da 0 a 29 dell'array.
  • Alla fine dovrebbe essere utilizzata ogni posizione dell'array e gli operatori dovrebbero apparire nell'array tante volte quante sono le percentuali di chiamate che dovrebbero ricevere.
  • In un ciclo, generare un numero casuale compreso tra 0 e 99 e assegnare la chiamata in arrivo al lavoratore in quella posizione dell'array. Se il lavoratore è occupato, ripetere.
  • In questo modo, per pura probabilità, le chiamate verranno distribuite come desiderato
  • Nel mio esempio, worker1 ha una probabilità 30/100 di essere scelto in una data iterazione.

4

Sono d'accordo con la soluzione di @ DocBrown. Inserendolo in un modulo algoritmo:

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
  • Il delta è determinato dalla percentuale effettiva meno la percentuale prevista di una linea. In questo modo, quelli con il delta negativo più grande sono quelli che più richiedono una chiamata per conformarsi alla percentuale prevista.

    Ad esempio, nel caso in cui le percentuali previste per le righe 1 e 2 siano rispettivamente del 60% e del 40% e le loro percentuali effettive siano del 50% e del 50%, si vedrà la riga di ordinamento 1 seguita dalla riga 2, da -10 % è inferiore al 10%. Quindi la linea 1 riceve la chiamata.

    Consiglio vivamente di utilizzare l'ordinamento per inserzione poiché funziona meglio quando l'array è già in gran parte ordinato.

Inoltre, come ottimizzazione minore, se si tiene traccia del numero totale di chiamate finora, anziché dover calcolare la percentuale effettiva di ciascuna linea, è possibile semplicemente calcolare il numero totale di chiamate per quella linea meno la percentuale prevista per quella linea per il numero totale di chiamate (delta = t_i - p_i * T). In questo caso il delta è semplicemente il numero negativo di chiamate per raggiungere la percentuale prevista.

Spero che chiarisca ogni altro dubbio.


grazie @Neil mi hai davvero aiutato ma quando entrambi colpiscono il segno, quindi quale linea dovrei chiamare allora, ci sono dei criteri per questo.
Akaku,

@akku Con il mio algoritmo, prendi semplicemente il primo sempre dopo l'ordinamento, il che significa che all'algoritmo non importa. Se hai altri criteri da applicare, devi farlo pesare di conseguenza quando lo ordini. In altre parole, se il numero di riga fosse importante, allora dovresti prendere il delta, moltiplicare per il numero totale di righe, quindi aggiungere il numero di riga corrente. Ciò favorisce numeri di riga più alti, supponendo che tutto il resto sia uguale.
Neil,

@Neil: la tua risposta va bene, ma ogni volta che vedo qualcuno che suggerisce di ordinare completamente un array solo per trovare il valore minimo, penso "Grande Scott, è davvero necessario?"
Doc Brown,

@DocBrown O(n)è ciò che puoi aspettarti di ordinare un elenco già ordinato con ordinamento di inserzione ed O(n)è ciò che dovresti usare per trovare il valore più piccolo. Presumo solo che sia stato risolto.
Neil,

@Neil: solo perché due algoritmi sono entrambi O (n), non sono ugualmente semplici (o altrettanto veloci).
Doc Brown,

2

Presupposti come indicato dall'OP

  1. Il numero di righe, n, è noto e;
  2. La% di ogni riga è nota

Algorithm Design

  1. Definisci ogni riga in base alla sua%

  2. Ordinare ogni riga in base alla sua posizione a partire da 0 definita come (% attuale di lavoratori -% assegnata di lavoratori) o per assegnazione casuale se tutte le linee = 0

  3. Inoltra ogni chiamata alla linea più grande da 0

Esempio: 3 righe con una percentuale rispettivamente di 20, 30 e 50. Al punto x nel tempo 1 persona chiama e poiché ogni linea è lontana da 0 a 0, viene assegnata in modo casuale - diciamo alla linea 2 che dovrebbe contenere il 30% di tutte le chiamate. Poiché la linea 2 dovrebbe contenere il 30% di tutte le chiamate e ora detiene il 100% di tutte le chiamate, la sua posizione da 0 aumenta. Il chiamante successivo verrebbe ora assegnato alla linea 1 o alla linea 3 ecc. Fino all'equilibrio (0) e quindi il loop si ripete.


0

Questa è una soluzione ingenua e non presuppone nulla ma consentirebbe una distribuzione basata su percentuale. Questa soluzione potrebbe essere migliorata in molti modi, ma questa è la sostanza. Non sono sicuro se questo è quello che stai cercando, ma ti darebbe una vera distribuzione.

codice psuedo ...

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
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.