Tuesday 22 September 2009

Generator for distributing calls

At work I was confronted with the problem of 'How to distribute calls between 2 call centers in a fair and even way according to some yet-to-be-determined percentage split ration?' Taking 30% split, we cannot send the first 30 to call centre 1 and the remaining 70 to call centre 2. The calls must be distributed as evenly as possible throughout; for example split 30% or 10 calls would give: [1,2,1,1,2,1,1,2,1,1] and not [1,1,1,1,1,1,1,2,2,2]!

When thinking about these kinds of problems, it helps to abstract away from the context of calls and call centres and think about the underlying problem; distribution over a descrete choice space. From here, we might find a solution in another domain that solves our problem...

It turns out that the problem of call distribution distils to the same problem that Bresenham tackled when trying to draw a line on a computer screen matrix. Imagine that you have a graph of cells 100 pixels on the X axis and 100 pixels on the Y axis. Now imagine you are using the line drawing algorithm to paint a line from the X/Y origin to, say, the coordinates '100,30'.

The line drawing algorithm will, after 100 interations, have distributed pixels evenly between 70 in the X direction and 30 in the Y direction (but always moving towards X). This is exactly the same as distributing 30 calls to call centre 1 and the rest to call centre 2.

To model this, it makes sense to write a python generator that 'yields' the correct call centre when asked:


class CallDistributor():
def __init__(self, split=50):
self.split = split
if split > 100 or split <= 0:
raise ValueError

def _execute(self):
error = 0.0
step = 0
deltaErr = self.split / 100.00
yield 1
while True:
error += deltaErr
if abs(error) >= 0.5:
yield 2
error -= 1.0
else:
yield 1

def __iter__(self):
return iter(self._execute( ))


if __name__ == "__main__":
dist1 = CallDistributor(split=50)
anIter = iter(dist1)
for i in range(10):
print anIter.next()


If I have chance I'd like to expand this to take a 'number of call centres' parameter, rather than having it restricted to 2.

No comments: