From dd8f2b8e06e7287767fbdac804f002b2e106251d Mon Sep 17 00:00:00 2001 From: rodrigoarenas456 <31422766+rodrigoarenas456@users.noreply.github.com> Date: Fri, 12 Mar 2021 15:07:06 -0500 Subject: [PATCH 1/9] Added codecov badge --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index 3877093..112f66b 100644 --- a/README.md +++ b/README.md @@ -1,5 +1,6 @@ [![Build Status](https://www.travis-ci.com/rodrigo-arenas/pyworkforce.svg?branch=main)](https://www.travis-ci.com/rodrigo-arenas/pyworkforce) +[![Codecov](https://codecov.io/gh/rodrigo-arenas/pyworkforce/branch/main/graphs/badge.svg?branch=main&service=github)](https://codecov.io/github/rodrigo-arenas/pyworkforce?branch=main) [![PyPI Version](https://badge.fury.io/py/pyworkforce.svg)](https://badge.fury.io/py/pyworkforce) [![Python Version](https://img.shields.io/badge/python-3.6%20%7C%203.7%20%7C%203.8%20%7C%203.9-blue)](https://www.python.org/downloads/) From 2d54910b9e103dc52618b188f6f9043598872c3c Mon Sep 17 00:00:00 2001 From: rodrigoarenas456 <31422766+rodrigoarenas456@users.noreply.github.com> Date: Fri, 12 Mar 2021 15:28:11 -0500 Subject: [PATCH 2/9] Added codecov badge and refactor style of features description --- README.md | 29 +++++++++++++++++++---------- 1 file changed, 19 insertions(+), 10 deletions(-) diff --git a/README.md b/README.md index 112f66b..96440bc 100644 --- a/README.md +++ b/README.md @@ -5,20 +5,33 @@ [![Python Version](https://img.shields.io/badge/python-3.6%20%7C%203.7%20%7C%203.8%20%7C%203.9-blue)](https://www.python.org/downloads/) - # pyworkforce -Common tools for workforce management, schedule and optimization problems built on top of packages like google's ortools +Common tools for workforce management, schedule and optimization problems built on top of packages like google's or-tools and custom modules +## Features: +pyworkforce currently includes: + +[Queue Systems](./pyworkforce/queuing): +- **queing.ErlangC:** Find the number of positions required to attend incoming traffic to a constant rate and infinite queue length + +[Shifts](./pyworkforce/shifts): +- **shifts.MinAbsDifference:** Find the number of resources to schedule in a shift, based in the number of required positions per time interval (found for example using [queing.ErlangC](./pyworkforce/queuing/erlang.py)), maximum capacity restrictions and static shifts coverage + + # Usage: For complete list and details of examples go to the [examples folder](https://github.com/rodrigo-arenas/pyworkforce/tree/develop/examples) -### Queue systems: +install pyworkforce -It can be used for solving the required number of positions to manage a number of transactions, -under some systems pre-defined parameters and goals. +``` +pip install pyworkforce +``` + +If you are having troubles with or-tools installation, check the [or-tools guide](https://github.com/google/or-tools#installation) +### Queue systems: #### Example: @@ -38,11 +51,7 @@ print("positions_requirements: ", positions_requirements) 'waiting_probability': 0.1741319335950498} ``` -### Shifts Design - -Find the optimal number of persons to assign to a pre-defined list of shifts, under a requirement of persons per period -of day and capacity restrictions - +### Shifts #### Example: ```python From 71db1b6d39025bcef3f04843d715704967124a1f Mon Sep 17 00:00:00 2001 From: rodrigoarenas456 <31422766+rodrigoarenas456@users.noreply.github.com> Date: Fri, 12 Mar 2021 15:43:02 -0500 Subject: [PATCH 3/9] Added restrictions and assumptions --- README.md | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 96440bc..76d0178 100644 --- a/README.md +++ b/README.md @@ -13,10 +13,11 @@ and custom modules pyworkforce currently includes: [Queue Systems](./pyworkforce/queuing): -- **queing.ErlangC:** Find the number of positions required to attend incoming traffic to a constant rate and infinite queue length +- **queing.ErlangC:** Find the number of positions required to attend incoming traffic to a constant rate and infinite queue length and no dropout. [Shifts](./pyworkforce/shifts): -- **shifts.MinAbsDifference:** Find the number of resources to schedule in a shift, based in the number of required positions per time interval (found for example using [queing.ErlangC](./pyworkforce/queuing/erlang.py)), maximum capacity restrictions and static shifts coverage +- **shifts.MinAbsDifference:** Find the number of resources to schedule in a shift, based in the number of required positions per time interval (found for example using [queing.ErlangC](./pyworkforce/queuing/erlang.py)), maximum capacity restrictions and static shifts coverage.
+This module finds the "optimal" assignation by minimizing the total absolute differences between required resources per interval, against the scheduled resources found by the solver. # Usage: From 14f002b19dbf8dd2c235349d4cba7cc1172bf84c Mon Sep 17 00:00:00 2001 From: Rodrigo Arenas <31422766+rodrigo-arenas@users.noreply.github.com> Date: Fri, 12 Mar 2021 21:10:32 -0500 Subject: [PATCH 4/9] Update issue templates --- .github/ISSUE_TEMPLATE/bug_report.md | 38 +++++++++++++++++++++++ .github/ISSUE_TEMPLATE/feature_request.md | 20 ++++++++++++ 2 files changed, 58 insertions(+) create mode 100644 .github/ISSUE_TEMPLATE/bug_report.md create mode 100644 .github/ISSUE_TEMPLATE/feature_request.md diff --git a/.github/ISSUE_TEMPLATE/bug_report.md b/.github/ISSUE_TEMPLATE/bug_report.md new file mode 100644 index 0000000..dd84ea7 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/bug_report.md @@ -0,0 +1,38 @@ +--- +name: Bug report +about: Create a report to help us improve +title: '' +labels: '' +assignees: '' + +--- + +**Describe the bug** +A clear and concise description of what the bug is. + +**To Reproduce** +Steps to reproduce the behavior: +1. Go to '...' +2. Click on '....' +3. Scroll down to '....' +4. See error + +**Expected behavior** +A clear and concise description of what you expected to happen. + +**Screenshots** +If applicable, add screenshots to help explain your problem. + +**Desktop (please complete the following information):** + - OS: [e.g. iOS] + - Browser [e.g. chrome, safari] + - Version [e.g. 22] + +**Smartphone (please complete the following information):** + - Device: [e.g. iPhone6] + - OS: [e.g. iOS8.1] + - Browser [e.g. stock browser, safari] + - Version [e.g. 22] + +**Additional context** +Add any other context about the problem here. diff --git a/.github/ISSUE_TEMPLATE/feature_request.md b/.github/ISSUE_TEMPLATE/feature_request.md new file mode 100644 index 0000000..bbcbbe7 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/feature_request.md @@ -0,0 +1,20 @@ +--- +name: Feature request +about: Suggest an idea for this project +title: '' +labels: '' +assignees: '' + +--- + +**Is your feature request related to a problem? Please describe.** +A clear and concise description of what the problem is. Ex. I'm always frustrated when [...] + +**Describe the solution you'd like** +A clear and concise description of what you want to happen. + +**Describe alternatives you've considered** +A clear and concise description of any alternative solutions or features you've considered. + +**Additional context** +Add any other context or screenshots about the feature request here. From d50822238922ebf2548f7528e14fac29623eb1a4 Mon Sep 17 00:00:00 2001 From: rodrigoarenas456 <31422766+rodrigoarenas456@users.noreply.github.com> Date: Mon, 15 Mar 2021 15:02:21 -0500 Subject: [PATCH 5/9] Set code coverage fails under 95% Little doc improvement in README.md --- .travis.yml | 2 +- README.md | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.travis.yml b/.travis.yml index e8bb964..6465615 100644 --- a/.travis.yml +++ b/.travis.yml @@ -10,6 +10,6 @@ before_install: install: - pip install -r dev-requirements.txt script: - - pytest pyworkforce/ --verbose --color=yes --assert=plain --cov-config=.coveragerc --cov=./ + - pytest pyworkforce/ --verbose --color=yes --assert=plain --cov-fail-under=95 --cov-config=.coveragerc --cov=./ after_success: - codecov diff --git a/README.md b/README.md index 76d0178..c6030e8 100644 --- a/README.md +++ b/README.md @@ -58,13 +58,13 @@ print("positions_requirements: ", positions_requirements) ```python from pyworkforce.shifts import MinAbsDifference -# Rows are the days, each entry of a row, is an hour of the day (24). +# Rows are the days, each entry of a row, is number of positions required at an hour of the day (24). required_resources = [ [9, 11, 17, 9, 7, 12, 5, 11, 8, 9, 18, 17, 8, 12, 16, 8, 7, 12, 11, 10, 13, 19, 16, 7], [13, 13, 12, 15, 18, 20, 13, 16, 17, 8, 13, 11, 6, 19, 11, 20, 19, 17, 10, 13, 14, 23, 16, 8] ] -# Each entry of a shift, is an hour of the day (24) +# Each entry of a shift,an hour of the day (24), 1 if the shift covers that hour, 0 otherwise shifts_coverage = {"Morning": [0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], "Afternoon": [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0], "Night": [1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1], From 73dddf17743a40ae5dc3d52d1c3464565f8a5e58 Mon Sep 17 00:00:00 2001 From: rodrigoarenas456 <31422766+rodrigoarenas456@users.noreply.github.com> Date: Mon, 15 Mar 2021 15:24:59 -0500 Subject: [PATCH 6/9] Several o.s for build test in travis-ci --- .travis.yml | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/.travis.yml b/.travis.yml index 6465615..811d192 100644 --- a/.travis.yml +++ b/.travis.yml @@ -4,6 +4,10 @@ python: - 3.7 - 3.8 - 3.9 +os: + - linux + - osx + - windows before_install: - python --version - pip install -U pip From 24ee57a745f75ae98299ee21ddaaa9966c88b345 Mon Sep 17 00:00:00 2001 From: rodrigoarenas456 <31422766+rodrigoarenas456@users.noreply.github.com> Date: Mon, 15 Mar 2021 15:38:00 -0500 Subject: [PATCH 7/9] Removed osx and windows due travis lack of support --- .travis.yml | 2 -- 1 file changed, 2 deletions(-) diff --git a/.travis.yml b/.travis.yml index 811d192..c32269e 100644 --- a/.travis.yml +++ b/.travis.yml @@ -6,8 +6,6 @@ python: - 3.9 os: - linux - - osx - - windows before_install: - python --version - pip install -U pip From df021122ad6b6a109067f68a6c777e59eef4188b Mon Sep 17 00:00:00 2001 From: rodrigoarenas456 <31422766+rodrigoarenas456@users.noreply.github.com> Date: Fri, 19 Mar 2021 02:05:02 -0500 Subject: [PATCH 8/9] Minor docs improvements --- pyworkforce/shifts/shifts_selection.py | 10 ++++------ setup.py | 3 --- 2 files changed, 4 insertions(+), 9 deletions(-) diff --git a/pyworkforce/shifts/shifts_selection.py b/pyworkforce/shifts/shifts_selection.py index 5d31cb5..24d380b 100644 --- a/pyworkforce/shifts/shifts_selection.py +++ b/pyworkforce/shifts/shifts_selection.py @@ -17,17 +17,16 @@ def __init__(self, num_days: int, Solves the following schedule problem: Its required to find the optimal number of resources (agents, operators, doctors, etc) to allocate - in a shift, based on a pre-defined requirement of # of resources per period of the day (periods of hours, + in a shift, based on a pre-defined requirement of number of resources per period of the day (periods of hours, half-hour, etc) - The optimal criteria, is defined as the amount of resources per shifts that minimize the total absolute + The "optimal" criteria, is defined as the amount of resources per shifts that minimize the total absolute difference, between the required resources per period and the actual shifted by the solver :param num_days: Number of days needed to schedule :param periods: Number of working periods in a day - :param shifts_coverage: dict with structure {"shift_name": "shift_array"} where "shift_array" is an array - of size [periods] (p), 1 if shift covers period p, 0 otherwise + :param shifts_coverage: dict with structure {"shift_name": "shift_array"} where "shift_array" is an array of size [periods] (p), 1 if shift covers period p, 0 otherwise :param max_period_concurrency: Maximum resources allowed to shift in any period and day :param required_resources: Array of size [days, periods] :param max_shift_concurrency: Number of maximum allowed resources in a same shift @@ -52,9 +51,9 @@ def __init__(self, num_days: int, self.required_resources = required_resources self.max_search_time = max_search_time self.num_search_workers = num_search_workers + self.solver = cp_model.CpSolver() self.transposed_shifts_coverage = None self.status = None - self.solver = None def solve(self): sch_model = cp_model.CpModel() @@ -100,7 +99,6 @@ def solve(self): sch_model.Minimize( sum(transition_resources[d][p] for d in range(self.num_days) for p in range(self.num_periods))) - self.solver = cp_model.CpSolver() self.solver.parameters.max_time_in_seconds = self.max_search_time self.solver.num_search_workers = self.num_search_workers diff --git a/setup.py b/setup.py index 084a2f8..7cce0b5 100644 --- a/setup.py +++ b/setup.py @@ -3,13 +3,10 @@ # twine upload --skip-existing --repository-url https://test.pypi.org/legacy/ dist/* -# The directory containing this file HERE = pathlib.Path(__file__).parent -# The text of the README file README = (HERE / "README.md").read_text() -# This call to setup() does all the work setup( name="pyworkforce", version="0.2.1", From 651a1acf00e6d8340fbe917186b23a9ad4daaac2 Mon Sep 17 00:00:00 2001 From: rodrigoarenas456 <31422766+rodrigoarenas456@users.noreply.github.com> Date: Fri, 19 Mar 2021 12:03:22 -0500 Subject: [PATCH 9/9] bump version to 0.2.2 --- README.md | 9 ++++++--- setup.py | 2 +- 2 files changed, 7 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index c6030e8..6551de3 100644 --- a/README.md +++ b/README.md @@ -43,8 +43,9 @@ erlang = ErlangC(transactions=100, asa=20/60, aht=3, interval=30, shrinkage=0.3) positions_requirements = erlang.required_positions(service_level=0.8, max_occupancy=0.85) print("positions_requirements: ", positions_requirements) - - +``` +Output: +``` >> positions_requirements: {'raw_positions': 14, 'positions': 20, 'service_level': 0.8883500191794669, @@ -80,7 +81,9 @@ scheduler = MinAbsDifference(num_days=2, solution = scheduler.solve() print("solution :", solution) - +``` +Output: +``` >> solution: {'status': 'OPTIMAL', 'cost': 157.0, 'resources_shifts': [{'day': 0, 'shift': 'Morning', 'resources': 8}, diff --git a/setup.py b/setup.py index 7cce0b5..f9563fa 100644 --- a/setup.py +++ b/setup.py @@ -9,7 +9,7 @@ setup( name="pyworkforce", - version="0.2.1", + version="0.2.2", description="Common tools for workforce management, schedule and optimization problems", long_description=README, long_description_content_type="text/markdown",