Thuật toán cho tỷ lệ phần trăm mà không biết tổng số


17

Giả sử có những ndòng cho một đường dây nóng.

Bất cứ khi nào khách hàng gọi đến đường dây nóng, cuộc gọi sẽ được chuyển tiếp đến một trong các nđường dây. Và tôi muốn chỉ định tỷ lệ phần trăm của cuộc gọi cho mỗi dòng n. Giả sử có hai dòng và một dòng được gán 60% và dòng khác là 40%, tổng số cuộc gọi là 10 nên dòng đầu tiên sẽ nhận được 6 cuộc gọi và thứ hai sẽ nhận được 4 cuộc gọi.

Tôi biết trước tỷ lệ cuộc gọi đến từng đường dây nhưng vấn đề là tôi không biết số lượng cuộc gọi sẽ nhận được trong một ngày.

Làm cách nào tôi có thể phân phối số lượng cuộc gọi mà không biết tổng số cuộc gọi?


2
Sau khi dòng 1 nhận được 6 cuộc gọi, hãy thực hiện cuộc gọi 2 dòng 4. Đó là, đừng quan tâm đến tổng số thực tế, quan tâm đến việc phân phối trong "khoảng thời gian" (10, trong trường hợp này) mà bạn biết. Rõ ràng bạn có thể làm những thứ như các dòng thay thế ngoại trừ giá trị cuối cùng, do đó cũng không cần phải chờ đợi nghiêm ngặt. Nếu có một số loại hàng đợi, hãy thực hiện tỷ lệ phần trăm dựa trên các hàng hiện tại trong hàng đợi.
Đồng hồ-Muse

"dấu hoa thị" và "DID" là gì?
gnat

@ Clockwork-Muse: Tôi sẽ đề nghị làm tròn số nguyên ở đây thay vì duy trì phân phối 6-4. Nếu không, phân phối của bạn sẽ bị tắt trừ khi bạn biết bạn có nhiều cuộc gọi chính xác gồm 10 cuộc gọi. Ví dụ: nếu tổng số 6 cuộc gọi đến, cách tiếp cận được đề xuất của bạn sẽ gán tất cả chúng cho dòng A; trong khi cách tiếp cận đúng hơn sẽ là 4 đến A và 2 đến B (được chỉ định theo thứ tự ABAABA nếu bạn làm tròn trên tổng số gán số nguyên cho mỗi dòng)
Flater

Câu trả lời:


26

Thực hiện một số kế toán về các cuộc gọi đã thực hiện và tính toán phân phối của chúng trên n dòng. Điều này cung cấp cho bạn n giá trị phần trăm (phân phối đã đạt được của bạn), có thể được so sánh với n phần trăm bạn muốn đạt được. Bất cứ khi nào có cuộc gọi mới, hãy gán cuộc gọi đó đến đường dây có độ lệch cao nhất so với giá trị đích (lưu ý rằng miễn là bạn không nhấn chính xác vào phân phối nhất định, luôn có một đường dây có quá ít cuộc gọi cho đến nay, khi so sánh với phân phối mục tiêu).

Ví dụ: sau khi chỉ định cuộc gọi đầu tiên cho dòng 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: Cách tiếp cận này có thể được cải thiện hơn nữa bằng cách không sử dụng sự khác biệt tuyệt đối, nhưng chọn đường thẳng giảm thiểu tổng bình phương của tất cả các độ lệch. Điều đó cũng sẽ cung cấp cho bạn một kết quả tốt hơn trong trường hợp bạn đạt được các giá trị đích chính xác.


2
Bạn có thể muốn thay đổi "miễn là" thành một tham chiếu rõ ràng hơn "sử dụng một tài liệu tham khảo tiebreaker khác", FWIW.
DougM

@DougM: xem chỉnh sửa của tôi.
Doc Brown

5
  • Giả sử số lượng công nhân ít hơn 100
  • Tạo một mảng công nhân với công suất 100
  • Đặt trong mảng đó một công nhân một số lần bằng tỷ lệ phần trăm của các cuộc gọi anh ta sẽ nhận được, ví dụ nếu worker1 sẽ nhận được 30% tất cả các cuộc gọi, sau đó đặt anh ta vào các vị trí từ 0 đến 29 của mảng.
  • Cuối cùng, mọi vị trí của mảng sẽ được sử dụng và các công nhân sẽ xuất hiện trong mảng nhiều lần như tỷ lệ phần trăm của các cuộc gọi mà họ sẽ nhận được.
  • Trong một vòng lặp, tạo một số ngẫu nhiên trong khoảng từ 0 đến 99 và gán cuộc gọi đến cho worker ở vị trí đó của mảng. Nếu công nhân bận, lặp lại.
  • Bằng cách đó, ngoài khả năng tuyệt đối, các cuộc gọi sẽ được phân phối như mong muốn
  • Trong ví dụ của tôi, worker1 có 30/100 cơ hội được chọn ở bất kỳ lần lặp nào.

4

Tôi đồng ý với giải pháp của @ DocBrown. Đặt nó vào một hình thức thuật toán:

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 được xác định bằng tỷ lệ phần trăm thực tế trừ đi tỷ lệ phần trăm dự kiến ​​của một dòng. Theo cách này, những người có đồng bằng âm lớn nhất là những người đòi hỏi nhiều nhất để gọi theo tỷ lệ phần trăm dự kiến.

    Ví dụ: trong trường hợp tỷ lệ phần trăm dự kiến ​​cho dòng 1 và 2 tương ứng là 60% và 40% và tỷ lệ phần trăm thực tế của chúng là 50% và 50%, bạn sẽ thấy dòng đặt hàng 1 theo sau là dòng 2, kể từ -10 % là dưới 10%. Do đó, dòng 1 sẽ nhận được cuộc gọi.

    Tôi đặc biệt khuyên bạn nên sử dụng sắp xếp chèn vì nó hoạt động tốt nhất khi mảng đã được sắp xếp chủ yếu.

Ngoài ra, như một tối ưu hóa nhỏ, nếu bạn theo dõi tổng số cuộc gọi cho đến nay, thay vì phải tính tỷ lệ phần trăm thực tế của mỗi dòng, bạn có thể chỉ cần tính tổng số cuộc gọi cho dòng đó trừ phần trăm dự kiến ​​cho số đó dòng nhân tổng số cuộc gọi (delta = t_i - p_i * T). Trong trường hợp này, delta chỉ đơn giản là số lượng cuộc gọi âm để đạt được tỷ lệ phần trăm mong đợi.

Tôi hy vọng rằng làm rõ bất kỳ nghi ngờ khác.


cảm ơn @Neil bạn thực sự đã giúp tôi nhưng khi cả hai đạt được mục đích thì tôi nên gọi dòng nào sau đó, có tiêu chí nào cho điều đó không.
akku

@akku Với thuật toán của tôi, bạn chỉ cần lấy cái đầu tiên luôn luôn sau khi sắp xếp, nghĩa là thuật toán không quan tâm. Nếu bạn có một tiêu chí khác để áp dụng, bạn phải làm cho nó cân nhắc phù hợp khi bạn sắp xếp nó. Nói cách khác, nếu số dòng là quan trọng, thì bạn nên lấy delta, nhân với tổng số dòng, sau đó thêm số dòng hiện tại. Điều đó ủng hộ số dòng cao hơn, giả sử tất cả những người khác đều bằng nhau.
Neil

@Neil: câu trả lời của bạn là tốt, nhưng bất cứ khi nào tôi thấy ai đó đề nghị sắp xếp một mảng hoàn toàn chỉ để tìm giá trị tối thiểu, tôi nghĩ "Great Scott, điều này có thực sự cần thiết không?"
Doc Brown

@DocBrown O(n)là những gì bạn có thể mong đợi sắp xếp một danh sách đã được sắp xếp với sắp xếp chèn và O(n)là những gì bạn phải sử dụng để tìm giá trị nhỏ nhất. Tôi chỉ giả sử có nó sắp xếp.
Neil

@Neil: chỉ vì hai thuật toán đều là O (n), chúng không đơn giản như nhau (hoặc nhanh như nhau).
Doc Brown

2

Giả định như OP đã nêu

  1. Số dòng, n, được biết và;
  2. % Của mỗi dòng được biết đến

Thiết kế thuật toán

  1. Xác định mỗi dòng theo% của nó

  2. Sắp xếp mỗi dòng theo vị trí của nó cách 0 được xác định là (% công nhân hiện tại - được gán% công nhân) hoặc theo phân công ngẫu nhiên nếu tất cả các dòng = 0

  3. Chuyển tiếp mỗi cuộc gọi đến đường dây lớn nhất từ ​​0

Ví dụ: 3 dòng với% tương ứng là 20, 30 và 50. Tại điểm x trong thời gian 1 người gọi và vì mỗi dòng là 0 từ 0, nên nó được chỉ định ngẫu nhiên - nói với dòng 2 sẽ giữ 30% tất cả các cuộc gọi. Vì dòng 2 sẽ giữ 30% tất cả các cuộc gọi và hiện giữ 100% tất cả các cuộc gọi, vị trí của nó từ 0 tăng lên. Người gọi tiếp theo bây giờ sẽ được gán cho dòng 1 hoặc dòng 3, vv cho đến khi cân bằng (0) và do đó vòng lặp lặp lại.


0

Đây là một giải pháp ngây thơ và không giả định gì nhưng sẽ cho phép phân phối dựa trên tỷ lệ phần trăm. Giải pháp này có thể được cải thiện theo nhiều cách nhưng đây là ý chính của nó. Tôi không chắc đây có phải là thứ bạn đang tìm kiếm không nhưng nó sẽ cung cấp cho bạn bản phân phối thực sự.

mã 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
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.