-1

Step 1: I have calculated the Capacity requirement for a set interval using the Erlang C formula (Ref: https://www.callcentrehelper.com/erlang-c-formula-example-121281.htm#:~:text=To%20work%20out%20the%20traffic,10%20Call%20Hours%20%3D%2010%20Erlangs.)


Input :

    Interval = 60 mins
    #Interactions = 171 calls
    AHT = 200 seconds
    Required SLA = 80%
    Target Answer Time = 120 seconds

Output:

    Required Capacity 

Code:

def power_fact(self, u, m):

    pow_fact = pow(u, m) / factorial(m)

    return pow_fact

def traffic_intensity(self, call, time_interval, avg_handling_time):

    if (call == 0) or (avg_handling_time == 0) or (time_interval == 0):
        traffic_inten = 0

    else:
        traffic_inten = (call / time_interval) * avg_handling_time

    return traffic_inten

def erlang_c(self, call, time_interval, avg_handling_time, agent_count):

    traffic_intensity_u = self.traffic_intensity(
        call, time_interval, avg_handling_time)

    power_factor = self.power_fact(traffic_intensity_u, agent_count)

    X = power_factor

    if (traffic_intensity_u == 0):
        p = 0
        Y = 0
        erlang = 0
        
    else:
        if (agent_count == 0):
            p = 0

        else:
            p = traffic_intensity_u / agent_count  # Agent Occupancy
            #print('Agent Occupancy: {}'.format(p))
        
        Y = 0
        for k in range(0, agent_count):
            Y += self.power_fact(traffic_intensity_u, k)

        erlang = X / (X + (1-p) * Y)

    return erlang

def ser_lev_agr(self, agent_count, call, time_interval, avg_handling_time, target_answer_time):
   
    traffic_intensity_u = self.traffic_intensity(
        call, time_interval, avg_handling_time)

    erlang = self.erlang_c(call, time_interval,
                           avg_handling_time, agent_count)

    exponential = exp(- (agent_count - traffic_intensity_u)
                      * (target_answer_time / avg_handling_time))

    service_level = 1 - (erlang * exponential)

    return service_level


def agents_needed(self, call, time_interval, avg_handling_time, target_SLA, target_answer_time):


    level = 0
    agent_count = 0

    while level < target_SLA:

        level = self.ser_lev_agr(
            agent_count, call, time_interval, avg_handling_time, target_answer_time)
        agent_count += 1

    return agent_count


Step2: I now need to calculate the number of interactions that can be handled, preferably using a similar technique, given the available capacity, while taking the required SLA into account.


Input :

    Interval = 60 mins
    Available Capacity  = 10 Hours
    AHT = 200 seconds
    Required SLA = 80%
    Target Answer Time = 120 seconds

Output:

    #Interactions

Any ideas on how I might be able to do this?

pb342
  • 1
  • 1
  • Hi, Have you tried or worked on step 2, if yes, please share your work and highlight where you are facing issues or need help. – Lakshya Srivastava Mar 22 '21 at 19:44
  • Hi, I am trying to solve the same equation mathematically but it is turning out to be a really complex equation to solve. Hence, I was looking for some ideas for a better approach. – pb342 Mar 23 '21 at 08:46

1 Answers1

0

For the first part:

You can use pyworkforce so you don't have to code it from scratch, with the data you provide is very straight foward, here is the code:

from pyworkforce.queuing import ErlangC

erlang = ErlangC(transactions=171, interval=60, asa=120/60, aht=200/60)
requirements = erlang.required_positions(service_level=0.8)

print(requirements)

Output:

{'raw_positions': 12, 
 'positions': 12, 
 'service_level': 0.9218549443574886, 
 'occupancy': 0.7916666666666666, 
 'waiting_probability': 0.3502218417740034}

Be aware that there are others parameters you can specify like shrinkage and max_occupancy

For the second part:

The second part is pretty much the same since you are constraining the SLA

You could plot # of transactions vs service level keeping fixed the number of resources (capacity) and choose the cutoff you want, for example, define a grid of the different range of transactions, in this example I'm gonna try 5 different options and leave all the others parameters with only 1 option, to try all different options at once, you need to use the MultiErlangC class from pyworkforce:

from pyworkforce.queuing import MultiErlangC

param_grid = {"transactions": [160, 165, 171, 175, 180], "aht": [200/60], "interval": [60], "asa": [120 / 60]}
erlang = MultiErlangC(param_grid=param_grid, n_jobs=-1)

print(erlang.param_list)

Now, you define your fixed capacity and pass it to the service_level method like this:

service_level_scenarios = {"positions": [12]}

requirements = erlang.service_level(arguments_grid=service_level_scenarios)

# 1 service level result per combination in the erlang.param_list and service_level_scenarios
print(requirements)

The output is the achieved service level for each of the 5 different options of transactions. You can make the grid bigger if you need a large set of transactions options

[0.9614481621520431, 0.9465713516901587, 0.9218549443574886, 0.8999506444946539, 0.8646468679398583]

So with this result and the input of transactions you can chosee the cutoff service level and look which transactions option leads to that service level.

You can see that the third service level (0.9218) is the one from 171 transactions, wich is consistent with what was found in part one, that is why I say is pretty much the same if you have the SLA as a constrain instead of looking at it as the result of your current capacity

Rodrigo A
  • 657
  • 7
  • 23