rodrigo-arenas / pyworkforce

Standard tools for workforce management, queuing, scheduling, rostering and optimization problems.
https://pyworkforce.readthedocs.io
MIT License
73 stars 19 forks source link

Remove CEIL from positions to create more accurate and less overestimate of capacity requirements #41

Closed sfghuis closed 1 year ago

sfghuis commented 1 year ago

Currently the roudning of positions prior tot multi-queue aggregations creates high overestimations of required capacities. This makes the package hard to use for capacity planning or scheduling. Is it possible to remove the rounding?

In addition could I collaborate on adding Erlang A to the package?

rodrigo-arenas commented 1 year ago

Hi @sfghuis the CEIL function is there because the definition of required resources is the minimum number of resources to get to a service level, in general, resources can't be a decimal number, Erlang C has to round up or down, if there is a round down, it breaks it's definition because it won't meet the service level, so it rounds up with CEIL, to ensure the service level, this is how pretty much all Erlang C calculators works

As for the second point, sure, go ahead! It could be useful to have Erlang A in the package

sfghuis commented 1 year ago

Hi @rodrigo-arenas , That might be so but the current usage creates a gross overestimation of required resources which translates in high positional requests when one wants to analyse or optimize of multiple queues for blending purposes. In addition the current setup also overestimates due to the position estimate incrementing with 1.

For example taking your test example (transactions=100, asa=0.33, aht=3, interval=30, shrinkage=0.3) results in 20 positions with shrinkage. Taking the same parameters using a stepsize of .1 and allowing float parameters using the gamma implementation results in 18.7 (19) positions with an expected SL of 81.6% which is closer to the set target of 80% with less positions. Given that typically calculations are run for multiple queues this overestimation stacks rapidely, even when for example the estimate is 18.01.

Please take a look into my fork where I added float support. In addition I started using a pydantic base setup for input validation, support of single and multiple scenarios using a single class for calls (though I am not that happy about my implementation yet)

Sorry if I am using the wrong method of communication here, this is my first time contributing towards an open source package.

rodrigo-arenas commented 1 year ago

Hi @sfghuis I understand the issue I'll take a look into the code, what I think it could be done, it's to implement an optional parameter named enforce_requirements or something like that, bool: default=True, if it's set to True it will keep the current ceiling behavior, if it's set to False, it won't make any rounding up or down

Also, make sure to check the test folder , this way we make sure we are not breaking anything

Another way to test this out is to compare the results with different inputs v.s some popular online calculators, like this one

About pydantic, I think it's a good idea to implement it as well

Greetings, and thanks for working on this

sfghuis commented 1 year ago

Hi @rodrigo-arenas,

I will update the test somewhere this week and add proper comments towards my fork. In addition I will rework into an Erlang C data class and a ErlangC class that can be used for calculations. Note that I have manually tested the output with the suggested calculator and it checks out.

I get the requirements for rounding but perhaps we should call it enforce_trafficking_requirements? As this would somewhat indicate in what type of situation the rounding should be applied? I saw that this is currently applied at multiple positions within the code. If I understand correctly we could simplify this by only applying the correction after shrinkage and recall the functions? This would reduce the need for checking within the functions themselves.

Having in mind that I will look into adding Erlang A and potententially non-small interval worktypes after this update perhaps we should decided on what structure is best?

Discussion questions for Erlang C

Currently I reworked the ErlangC class that it takes a set of queue - interval parameter input that can either take multple or single input values. This would split the calculation logic from the data requirements and allow for clear validations on the input data.

{'a queue': {parameter a: value, parameter b: p[value A, value B}} this returns {'a queue 1.0': ErlangC_data_class, 'a queue 1.1': ErlangC_dataclass}

I am implementing a return as dataframe that returns the resulting data into a pandas df. Giving some backwards compatibility I think adding a return as dict would also make sense, what do you think?

Discussion package structure

-- Current -- Pyworkforce queuing -- Erlang

Given that we will expand toward multiple erlang and potentially other work types, could we restructure towards:

Pyworkforce Worktypes -- real_time_queing --- queuing_test --- queuing_utils --- ErlangC --- ErlangA

(-- stand for a folder level) This way we could easily expend for mail and or chat in the future.

rodrigo-arenas commented 1 year ago

Closing this issue due to inactivity, let me know if still interested on this