Toplam sayı bilmeden yüzde algoritması


17

nBir telefon hattı için hatlar olduğunu varsayalım .

Bir müşteri yardım hattını her aradığında, çağrı nhatlardan birine yönlendirilir . Ve n hattın her birine çağrı yüzdesi atamak istiyorum. Varsayalım ki iki hat var ve bir hat% 60, diğeri% 40, toplam arama sayısı 10'dur, bu nedenle ilk hat 6 çağrı alır ve ikinci hat 4 çağrı alır.

Önceden her hat için arama yüzdesini biliyorum ama sorun ben bir gün içinde yapılacak olan çağrıların sayısını bilmiyorum olmasıdır.

Toplam aramayı bilmeden arama sayısını nasıl dağıtabilirim?


2
Hat 1 6 çağrı yaptıktan sonra hat 2 4 çağrı yapın. Yani, gerçek toplam sayıyı umursamayın, bildiğiniz "dönem" (bu durumda 10) boyunca dağılımı önemseyin. Açıkçası son değer dışında alternatif çizgiler gibi şeyler yapabilirsiniz, bu yüzden de katı bir bekleme gerekli değildir. Bir çeşit kuyruk varsa, yüzde, kuyruktaki geçerli satırlara göre yapın.
Clockwork-Muse

"yıldız" ve "DID" nedir?
gnat

@ Clockwork-Muse: 6-4 dağılımını korumak yerine burada tamsayıların yuvarlanmasını öneririm. Aksi takdirde, 10 aramanın tam katı olduğunu bilmediğiniz sürece dağıtımınız kapanacaktır. Örneğin, toplam 6 çağrı gelirse, önerilen yaklaşımınız hepsini A hattına atayacaktır; Daha doğru bir yaklaşım B A 4 ve 2 olacaktır, oysa (her hat için eğer yuvarlak tam sayı atama toplamları siparişi ABAABA tahsis)
flater

Yanıtlar:


26

Önceden alınmış aramalar hakkında bir miktar defter tutma ve n hattı üzerinden dağılımlarını hesaplayın. Bu, elde etmek istediğiniz n yüzdeyle karşılaştırılabilecek n yüzde değeri (önceden elde edilmiş dağıtımınız) verir. Yeni bir çağrı geldiğinde, bu çağrıyı hedef değerden en yüksek sapmaya sahip hatta atayın (verilen dağılıma tam olarak vurmadığınız sürece, şimdiye kadar çok az çağrı olan bir hat olduğunu unutmayın, hedef dağılım ile karşılaştırıldığında).

Örneğin: hat 1'e ilk çağrıyı atadıktan sonra:

 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

...

DÜZENLEME: Bu yaklaşım, mutlak farkı kullanmadan, ancak tüm sapmaların kareler toplamını en aza indiren çizgiyi seçerek daha da geliştirilebilir. Bu, hedef değerlere tam olarak ulaşmanız durumunda size daha iyi bir sonuç verir.


2
"Daha açık" bir "farklı bir tiebreaker kullanın" başvurusu olan FWIW olarak değiştirmek isteyebilirsiniz.
DougM

@ DougM: düzenlememe bakın.
Doc Brown

5
  • Diyelim ki işçi sayısı 100'den az
  • 100 kişilik bir işçi grubu yaratın
  • Bu diziye bir çalışanı, alması gereken çağrıların yüzdesine eşit sayıda koyun, örneğin worker1 tüm çağrıların% 30'unu alması gerekiyorsa, onu dizinin 0 ila 29 konumlarına yerleştirin.
  • Sonunda dizinin her konumu kullanılmalı ve çalışanlar dizide almaları gereken çağrıların yüzdesi kadar fazla görünmelidir.
  • Bir döngüde, 0 ile 99 arasında rastgele bir sayı oluşturun ve gelen çağrıyı dizinin bu konumundaki çalışana atayın. Çalışan meşgulse, tekrarlayın.
  • Bu şekilde, olasılıklar dışında, çağrılar istendiği gibi dağıtılacaktır
  • Örneğimde, worker1 öğesinin belirli bir yinelemede seçilme şansı 30/100.

4

@ DocBrown'un çözümüne katılıyorum. Bir algoritma formuna yerleştirme:

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, fiili yüzde eksi bir çizginin beklenen yüzdesi ile belirlenir. Bu şekilde, en büyük negatif deltaya sahip olanlar, beklenen yüzdeye uymak için en çok çağrı talep edenlerdir.

    Örneğin, satır 1 ve 2 için beklenen yüzdelerin sırasıyla% 60 ve% 40 olduğu ve gerçek yüzdelerinin% 50 ve% 50 olduğu durumda, sipariş satır 1'i ve ardından satır 2'yi göreceksiniz, çünkü -10 %,% 10'dan azdır. Böylece 1. hat çağrıyı alacaktı.

    Dizi çoğunlukla sıralanmış zaman en iyi performans çünkü ekleme sıralama kullanmanızı tavsiye ederim.

Ayrıca, küçük bir optimizasyon olarak, her bir hattın gerçek yüzdesini hesaplamak yerine şimdiye kadar toplam çağrı sayısını izlerseniz, o hat için toplam çağrı sayısını eksi bunun için beklenen yüzdeyi hesaplayabilirsiniz. hat, toplam arama sayısının çarpı (delta = t_i - p_i * T). Bu durumda delta, beklenen yüzdeyi elde etmek için sadece negatif çağrı sayısıdır.

Umarım bu diğer şüpheleri açıklığa kavuşturur.


Teşekkürler @Neil gerçekten bana yardım ettiniz ama her ikisi de işareti vurduğunda hangi hattı aramalıyım, bunun için herhangi bir kriter var.
akku

@akku Algoritmamla, sıralamadan sonra her zaman ilkini alırsınız, yani algoritma umursamaz. Uygulanacak başka kriterleriniz varsa, sıralarken buna göre tartım yapmanız gerekir. Başka bir deyişle, satır numarası önemliyse, deltayı almalı, toplam satır sayısıyla çarpmalı ve ardından geçerli satır numarasını eklemelisiniz. Bu, diğerlerinin eşit olduğu varsayılarak daha yüksek satır numaralarını destekler.
Neil

@Neil: Cevabınız iyi, ama ne zaman birisini sadece minimum değeri bulmak için bir diziyi sıralamayı önerdiğini gördüğümde, bence "Büyük Scott, bu gerçekten gerekli mi?"
Doc Brown

@DocBrown O(n), zaten sıralanmış bir listeyi ekleme sıralamasıyla sıralamayı bekleyebileceğiniz O(n)ve en küçük değeri bulmak için kullanmanız gereken şeydir. Ben sadece sıralama var sanırım.
Neil

@Neil: iki algoritmanın ikisi de O (n) olduğu için, aynı derecede basit (ya da eşit derecede hızlı) değillerdir.
Doc Brown

2

OP tarafından belirtilen varsayımlar

  1. Çizgi sayısı, n, bilinir ve;
  2. Her satırın yüzdesi biliniyor

Algoritma Tasarımı

  1. Her satırı% ile tanımlayın

  2. Her satırı, (çalışanların geçerli yüzdesi - çalışanların yüzdesi atanmış) olarak tanımlanan 0'dan veya tüm satırlar = 0 ise rastgele atamaya göre konumlarına göre sıralayın

  3. Her çağrıyı 0'dan uzakta en büyük hatta yönlendir

Örnek: Sırasıyla% 20, 30 ve 50 olan 3 satır. Zaman x noktasında 1 kişi çağırır ve her hat 0'dan 0 uzak olduğundan, rastgele atanır - tüm aramaların% 30'unu tutması gereken hat 2'ye. Hat 2, tüm aramaların% 30'unu tutmalı ve şimdi tüm aramaların% 100'ünü tuttuğundan, 0'dan konumu artar. Bir sonraki arayan şimdi denge (0) olana kadar hat 1 veya hat 3'e atanır ve böylece döngü kendini tekrar eder.


0

Bu naif bir çözümdür ve yüzde esaslı dağıtıma izin vermek dışında hiçbir şey varsaymaz. Bu çözüm birçok yönden geliştirilebilir, ancak bunun özü budur. Aradığın şey olduğundan emin değilim ama sana gerçek bir dağıtım verecek.

psuedo kodu ...

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
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.