총 수를 모르는 비율에 대한 알고리즘


17

n핫라인에 대한 회선 이 있다고 가정하십시오 .

고객이 핫라인에 전화 할 때마다 통화가 n회선 중 하나로 전달됩니다 . 그리고 각 n 줄에 통화 비율을 할당하고 싶습니다. 두 개의 회선이 있고 한 회선에 60 %가 할당되고 다른 회선에 40 %가 할당되었다고 가정하면 총 통화 수는 10이므로 첫 번째 회선은 6 개의 통화를 받고 두 번째 회선은 4 개의 통화를받습니다.

사전에 각 회선으로 전화를 거는 비율을 알고 있지만 문제는 하루에받을 전화 수를 모르는 것입니다.

총 통화를 모른 채 통화 수를 어떻게 분배 할 수 있습니까?


2
회선 1이 6 번의 전화를받은 후 회선 2에 4 번의 전화를 겁니다. 즉, 실제 총 수는 신경 쓰지 말고 알고있는 "기간"(이 경우 10)을 통한 분포를 신경 쓰십시오. 분명히 마지막 값을 제외하고 대체 줄과 같은 작업을 수행 할 수 있으므로 엄격한 대기가 필요하지 않습니다. 대기열이 있으면 대기열의 현재 행을 기준으로 백분율을 수행하십시오.
Clockwork-Muse

"별표"와 "DID"는 무엇입니까?
gnat

@ Clockwork-Muse : 6-4 분포를 유지하는 대신 정수를 반올림하는 것이 좋습니다. 그렇지 않으면 10 번의 정확한 배수가 있다는 것을 알지 못하면 배포가 중단됩니다. 예를 들어 총 6 번의 전화가 걸려 오면 제안 된 접근 방식으로 모든 전화를 A 회선에 할당합니다. 더 정확한 접근 방법은 4에서 A, 2에서 B로입니다 (각 줄에 정수 할당 총계를 반올림하면 ABAABA 순서로 할당 됨)
Flater

답변:


26

이미 걸려온 전화에 대해 약간의 부기 작업을 수행하고 n 줄에 대한 분포를 계산하십시오. 이를 통해 n 퍼센트 값 (이미 달성 된 분포)을 얻을 수 있으며 n 퍼센트와 비교할 수 있습니다. 새 전화가 올 때마다 해당 통화를 목표 값과 가장 큰 편차가있는 회선에 할당하십시오 (주어진 분포를 정확하게 맞추지 않는 한 항상 통화가 너무 적은 회선이 있음에 유의하십시오. 목표 분포와 비교할 때).

예를 들어, 첫 번째 통화를 라인 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

...

편집 :이 방법은 절대 차이를 사용하지 않고 모든 편차의 제곱합을 최소화하는 선을 선택하여 더 향상 될 수 있습니다. 목표 값에 정확하게 도달하면 더 나은 결과를 얻을 수 있습니다.


2
FWIW라는 "명확한"다른 순위 결정 사용 "참조로"길이 "를 변경할 수 있습니다.
DougM

@ DougM : 내 편집을 참조하십시오.
Doc Brown

5
  • 근로자 수가 100 명 미만이라고 가정 해 봅시다
  • 수용 인원이 100 인 작업자 배열 만들기
  • 예를 들어 worker1이 모든 호출의 30 %를 가져와야하는 경우 배열의 0-29 위치에 배치해야합니다.
  • 마지막에 배열의 모든 위치를 사용해야하며 작업자는 호출의 비율에 따라 배열에 여러 번 나타나야합니다.
  • 루프에서 0에서 99 사이 의 난수를 생성 하고 배열의 해당 위치에서 작업자에게 수신 전화를 할당하십시오. 작업자가 바쁘면 반복하십시오.
  • 그런 식으로, 순전 한 확률로, 원하는대로 통화가 분배됩니다
  • 내 예에서 worker1은 주어진 반복에서 30/100 확률을 선택할 수 있습니다.

4

@DocBrown의 솔루션에 동의합니다. 알고리즘 형태로 배치 :

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
  • 델타는 실제 백분율에서 줄의 예상 백분율을 뺀 값으로 결정됩니다. 이런 식으로, 네거티브 델타가 가장 큰 사람들은 예상 비율에 따라 전화를 가장 많이 요구하는 것들입니다.

    예를 들어 1 행과 2 행의 예상 백분율이 각각 60 %와 40 %이고 실제 백분율이 50 %와 50 % 인 경우 -10 이후에 주문 행 1과 2 행이 표시됩니다. %가 10 % 미만입니다. 따라서 1 행은 전화를받습니다.

    배열이 이미 대부분 정렬되었을 때 가장 잘 수행되므로 삽입 정렬을 사용하는 것이 좋습니다.

또한 사소한 최적화로 각 회선의 실제 백분율을 계산하지 않고 지금까지의 총 통화 수를 추적하는 경우 해당 회선의 총 통화 수에서 예상 통화 비율을 뺀 값만 계산하면됩니다. 라인 횟수 총 통화 수 (델타 = t_i-p_i * T). 이 경우 델타는 단순히 예상 백분율을 달성하기위한 마이너스 호출 횟수입니다.

나는 그것이 다른 의심을 분명히하기를 바랍니다.


덕분에 @ Neil 정말 도움이되었지만 둘 다 전화를 걸어 어느 라인을 호출 해야하는지에 대한 기준이 있습니까?
akku

@akku 내 알고리즘을 사용하면 정렬 후 항상 첫 번째를 취하기 때문에 알고리즘이 중요하지 않습니다. 적용 할 다른 기준이있는 경우 분류 할 때 그에 따라 무게를 측정해야합니다. 즉, 줄 번호가 중요한 경우 델타에 총 줄 수를 곱한 다음 현재 줄 번호를 추가해야합니다. 다른 모든 항목이 동일하다고 가정하면 더 높은 행 번호를 선호합니다.
Neil

@ Neil : 귀하의 대답은 훌륭하지만 최소값을 찾기 위해 배열을 완전히 정렬하도록 제안하는 사람을 볼 때마다 "Great Scott, 이것이 정말로 필요합니까?"라고 생각합니다.
Doc Brown

@DocBrown O(n)은 삽입 정렬 O(n)을 사용하여 이미 정렬 된 목록을 정렬 할 수있는 것으로 가장 작은 값을 찾는 데 사용해야합니다. 방금 정렬했다고 가정합니다.
Neil

@Neil : 두 알고리즘이 모두 O (n)이기 때문에 똑같이 단순하지도 않습니다.
Doc Brown

2

OP가 명시한 가정

  1. 줄 수 n은 알려져 있으며;
  2. 각 줄의 %는 알려져 있습니다

알고리즘 설계

  1. 각 줄을 %로 정의

  2. (현재 근로자의 %-근로자의 할당 된 %)로 정의 된 0에서 떨어진 위치 또는 모든 라인이 0 인 경우 무작위 할당으로 각 라인을 정렬합니다.

  3. 각 통화를 0에서 가장 큰 회선으로 전달

예 : %가 각각 20, 30 및 50 인 3 줄. 1 번의 x 지점에서 1 명이 전화를 걸고 모든 회선이 0에서 0 떨어져 있기 때문에 무작위로 할당됩니다. 2 번 회선은 모든 통화의 30 %를 보유해야합니다. 2 행은 모든 통화의 30 %를 유지해야하고 이제 모든 통화의 100 %를 보유하므로 위치가 0에서 증가합니다. 다음 호출자는 평형 (0)까지 루프 1이 반복 될 때까지 라인 1 또는 라인 3 등에 할당됩니다.


0

이것은 순진한 솔루션이며 아무 것도 가정하지 않고 백분율 기반 배포를 허용합니다. 이 솔루션은 여러 가지 방법으로 개선 될 수 있지만 이것이 핵심입니다. 이것이 당신이 찾고있는 것인지 확실하지 않지만 진정한 분포를 줄 것입니다.

의사 코드 ...

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
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.