Rostering Problems ================== Introduction ------------ In workforce management, rostering means assigning named resources to days and shifts while respecting operational rules. The required number of resources per day and shift might come from a scheduling model, a demand forecast, or a manual planning process. The meaning of "optimal" is defined by an objective function. In this solver, the objective is to minimize scheduled hours while still satisfying the required coverage and roster constraints. pyworkforce solves this problem with ``MinHoursRoster``. MinHoursRoster -------------- This method assigns a list of resources to a list of required positions per day and shifts; it considers restrictions such as shift bans, non-sequential shifts, rest days, minimum hours, and other roster rules. It can also use soft preferences, such as a resource preferring a particular shift. The "optimal" criterion is the minimum total scheduled hours, optionally weighted by resource shift preferences. Let's start by introducing the variables that the model uses. ==================== ================== ===================================== Name Type Description ==================== ================== ===================================== :math:`D` Set Days on the planning horizon :math:`S` Set Shifts in a day :math:`N` Set Resources available to schedule :math:`\delta_s` Parameter Number of hours in the shift `s` :math:`\mu` Parameter Maximum number of days off per resource in the planning horizon :math:`R_{ds}` Parameter Number of resources required at day `d` for the shift `s` :math:`\tau_{ij}` Parameter 1 if a resource cannot work shift `j` the day after shift `i`, 0 otherwise :math:`\sigma_{nds}` Parameter 1 if resource `n` cannot work shift `s` on day `d`, 0 otherwise :math:`\phi_{ns}` Parameter 1 if resource `n` prefers shift `s`, 0 if there is no specific preference :math:`\alpha_{n}` Parameter Weight used to reward resource `n` when one of their shift preferences is met :math:`X_{nds}` Decision variable 1 if the resource `n` is scheduled at day `d` for the shift `s`, 0 otherwise ==================== ================== ===================================== In this case, the variables :math:`\tau_{ij}`, :math:`\phi_{ns}`, and :math:`\alpha_{n}` are optional for the solver. Under this definition, the objective function is formulated as: .. math:: min \sum_{n, d, s} (\delta_s - \alpha_{n}*\phi_{ns})*X_{nds} If the shift preference term :math:`\phi_{ns}` is not used, or if it is set to :math:`\phi_{ns} = 0_{n,s}`, the objective function simplifies to the total number of scheduled hours: .. math:: min \sum_{n, d, s} \delta_s*X_{nds} The model uses these restrictions: * The number of resources in the roster for day `d` and shift `s` must be greater or equal to the number of required resources for that day and shift. .. math:: \sum_{n} X_{nds} \geq R_{ds} \; \forall d \in D, \forall s \in S * The total days off for resource `n` cannot be greater than the maximum allowed days. .. math:: \sum_{d, s} 1- X_{nds} \leq \mu \; \forall n \in N * Each resource can be scheduled at most once per day. .. math:: \sum_{s} X_{nds} \leq 1 \; \forall d \in D, \forall n \in N * A resource cannot work forbidden shift sequences, according to :math:`\tau_{ij}`. .. math:: \sum_{j \in S} X_{nds}*\tau_{sj} + X_{n(d+1)s} \leq 1 \; \forall d \in D, \forall n \in N, \forall s \in S * Resources with a banned shift cannot be assigned to that shift. .. math:: \sum_{n, d, s} \sigma_{nds}*X_{nds} = 0 We'll solve an example using pyworkforce with the following conditions: * We want to plan a 7-day operation * The resources are people, and there are 55 resources available * There are four shifts: Morning, Afternoon, Night, and Mixed. All last 8 hours except Mixed, which lasts 6 hours * The minimum working hours in the 7-day horizon are 40 * Each resource can be off at most one day in this planning horizon * A resource who works Night cannot work Morning the following day * e.johnston@randatmail.com cannot work Night on day 0 or Morning on day 3 * d.harper@randatmail.com cannot work Mixed on day 1 * d.harper@randatmail.com prefers Morning or Mixed shifts when possible * c.campbell@randatmail.com prefers Afternoon shifts when possible * There is no special prioritization among resource shift preferences * The minimum required resources per shift and day are encoded in ``required_resources`` This data encodes all the previous conditions: .. code:: python3 shifts_info = { "num_days": 7, "resources": ["e.johnston@randatmail.com", "d.harper@randatmail.com", "m.hawkins@randatmail.com", "m.ellis@randatmail.com", "b.campbell@randatmail.com", "s.richards@randatmail.com", "j.evans@randatmail.com", "s.brooks@randatmail.com", "a.montgomery@randatmail.com", "c.hunt@randatmail.com", "v.owens@randatmail.com", "a.brown@randatmail.com", "r.armstrong@randatmail.com", "m.murray@randatmail.com", "b.evans@randatmail.com", "m.brown@randatmail.com", "s.thompson@randatmail.com", "a.ryan@randatmail.com", "r.carter@randatmail.com", "j.payne@randatmail.com", "s.perkins@randatmail.com", "t.west@randatmail.com", "d.stevens@randatmail.com", "l.gibson@randatmail.com", "m.crawford@randatmail.com", "a.barnes@randatmail.com", "m.howard@randatmail.com", "t.chapman@randatmail.com", "s.harris@randatmail.com", "a.farrell@randatmail.com", "d.douglas@randatmail.com", "a.douglas@randatmail.com", "j.cole@randatmail.com", "v.myers@randatmail.com", "l.owens@randatmail.com", "h.robinson@randatmail.com", "s.spencer@randatmail.com", "v.brooks@randatmail.com", "h.turner@randatmail.com", "e.elliott@randatmail.com", "a.adams@randatmail.com", "m.higgins@randatmail.com", "j.cole@randatmail.com", "m.ryan@randatmail.com", "l.wilson@randatmail.com", "j.higgins@randatmail.com", "v.ryan@randatmail.com", "c.perry@randatmail.com", "c.wright@randatmail.com", "f.myers@randatmail.com", "c.allen@randatmail.com", "c.stevens@randatmail.com", "c.campbell@randatmail.com", "d.taylor@randatmail.com", "h.myers@randatmail.com"], "shifts": ["Morning", "Afternoon", "Night", "Mixed"], "shifts_hours": [8, 8, 8, 6], "min_working_hours": 40, "max_resting": 1, "non_sequential_shifts": [{"origin": "Night", "destination": "Morning"}], "banned_shifts": [{"resource": "e.johnston@randatmail.com", "shift": "Night", "day": 0}, {"resource": "e.johnston@randatmail.com", "shift": "Morning", "day": 3}, {"resource": "d.harper@randatmail.com", "shift": "Mixed", "day": 1}], "required_resources": {"Morning": [9, 12, 8, 10, 13, 10, 14], "Afternoon": [11, 13, 10, 11, 9, 11, 7], "Night": [8, 7, 5, 15, 7, 8, 6], "Mixed": [2, 4, 18, 7, 10, 5, 17]}, "resources_preferences": [{"resource": "d.harper@randatmail.com", "shift": "Morning"}, {"resource": "d.harper@randatmail.com", "shift": "Mixed"}, {"resource": "c.campbell@randatmail.com", "shift": "Afternoon"}] } With this information, we can start using the :class:`~pyworkforce.rostering.MinHoursRoster` solver. .. code:: python3 from pyworkforce.rostering.binary_programming import MinHoursRoster from pprint import PrettyPrinter solver = MinHoursRoster(num_days=shifts_info["num_days"], resources=shifts_info["resources"], shifts=shifts_info["shifts"], shifts_hours=shifts_info["shifts_hours"], min_working_hours=shifts_info["min_working_hours"], max_resting=shifts_info["max_resting"], non_sequential_shifts=shifts_info["non_sequential_shifts"], banned_shifts=shifts_info["banned_shifts"], required_resources=shifts_info["required_resources"], resources_preferences=shifts_info["resources_preferences"]) pp.pprint(solver.solve()) The output is large, so this section explains the important fields first. The full printed solution is included at the end of this article. First, the ``OPTIMAL`` status means that the solver found the best feasible roster for the model. There are 330 assigned shifts, representing 2388 scheduled working hours. ``resource_shifts`` is a list of dictionaries. Each item tells you which resource is scheduled on which day and shift. For example, the first item means that e.johnston@randatmail.com works the Mixed shift on day 0: .. code:: python3 { 'day': 0, 'resource': 'e.johnston@randatmail.com', 'shift': 'Mixed'} ``resting_resource`` tells you which resource is off on each day. For example, the first item means that e.johnston@randatmail.com is off on day 3: .. code:: python3 {'day': 3, 'resource': 'e.johnston@randatmail.com'} ``resting_days`` is 55, the total number of days off in the planning horizon. Since there are 55 resources and each resource can rest at most one day, this means every resource rests exactly once. Now let's inspect a few resources with special conditions: * e.johnston@randatmail.com has two banned shifts: Night on day 0 and Morning on day 3. The solver respects both conditions by assigning Mixed on day 0 and a rest day on day 3. .. code:: python3 [ { 'day': 0, 'resource': 'e.johnston@randatmail.com', 'shift': 'Mixed'}, { 'day': 1, 'resource': 'e.johnston@randatmail.com', 'shift': 'Morning'}, { 'day': 2, 'resource': 'e.johnston@randatmail.com', 'shift': 'Night'}, { 'day': 4, 'resource': 'e.johnston@randatmail.com', 'shift': 'Morning'}, { 'day': 5, 'resource': 'e.johnston@randatmail.com', 'shift': 'Morning'}, { 'day': 6, 'resource': 'e.johnston@randatmail.com', 'shift': 'Morning'} ] * d.harper@randatmail.com cannot work Mixed on day 1 and prefers Morning or Mixed shifts. The ban is respected because he is off on day 1. The solver also assigns him to Morning shifts, which matches one of his preferences. Preferences are soft constraints: the solver tries to satisfy them without making the model infeasible or sacrificing optimality. .. code:: python3 [{ 'day': 0, 'resource': 'd.harper@randatmail.com', 'shift': 'Morning'}, { 'day': 2, 'resource': 'd.harper@randatmail.com', 'shift': 'Morning'}, { 'day': 3, 'resource': 'd.harper@randatmail.com', 'shift': 'Morning'}, { 'day': 4, 'resource': 'd.harper@randatmail.com', 'shift': 'Morning'}, { 'day': 5, 'resource': 'd.harper@randatmail.com', 'shift': 'Morning'}, { 'day': 6, 'resource': 'd.harper@randatmail.com', 'shift': 'Morning'}] * c.campbell@randatmail.com prefers Afternoon shifts: .. code:: python3 [{ 'day': 0, 'resource': 'c.campbell@randatmail.com', 'shift': 'Afternoon'}, { 'day': 1, 'resource': 'c.campbell@randatmail.com', 'shift': 'Afternoon'}, { 'day': 2, 'resource': 'c.campbell@randatmail.com', 'shift': 'Afternoon'}, { 'day': 3, 'resource': 'c.campbell@randatmail.com', 'shift': 'Afternoon'}, { 'day': 4, 'resource': 'c.campbell@randatmail.com', 'shift': 'Afternoon'}, { 'day': 5, 'resource': 'c.campbell@randatmail.com', 'shift': 'Afternoon'}] Here is the full print of the solution found by the solver: .. code:: python3 {'cost': 2376.0, 'resource_shifts': [ { 'day': 0, 'resource': 'e.johnston@randatmail.com', 'shift': 'Mixed'}, { 'day': 1, 'resource': 'e.johnston@randatmail.com', 'shift': 'Morning'}, { 'day': 2, 'resource': 'e.johnston@randatmail.com', 'shift': 'Night'}, { 'day': 4, 'resource': 'e.johnston@randatmail.com', 'shift': 'Morning'}, { 'day': 5, 'resource': 'e.johnston@randatmail.com', 'shift': 'Morning'}, { 'day': 6, 'resource': 'e.johnston@randatmail.com', 'shift': 'Morning'}, { 'day': 0, 'resource': 'd.harper@randatmail.com', 'shift': 'Morning'}, { 'day': 2, 'resource': 'd.harper@randatmail.com', 'shift': 'Morning'}, { 'day': 3, 'resource': 'd.harper@randatmail.com', 'shift': 'Morning'}, { 'day': 4, 'resource': 'd.harper@randatmail.com', 'shift': 'Morning'}, { 'day': 5, 'resource': 'd.harper@randatmail.com', 'shift': 'Morning'}, { 'day': 6, 'resource': 'd.harper@randatmail.com', 'shift': 'Morning'}, { 'day': 0, 'resource': 'm.hawkins@randatmail.com', 'shift': 'Mixed'}, { 'day': 1, 'resource': 'm.hawkins@randatmail.com', 'shift': 'Afternoon'}, { 'day': 2, 'resource': 'm.hawkins@randatmail.com', 'shift': 'Mixed'}, { 'day': 3, 'resource': 'm.hawkins@randatmail.com', 'shift': 'Night'}, { 'day': 5, 'resource': 'm.hawkins@randatmail.com', 'shift': 'Mixed'}, { 'day': 6, 'resource': 'm.hawkins@randatmail.com', 'shift': 'Mixed'}, { 'day': 0, 'resource': 'm.ellis@randatmail.com', 'shift': 'Mixed'}, { 'day': 1, 'resource': 'm.ellis@randatmail.com', 'shift': 'Afternoon'}, { 'day': 2, 'resource': 'm.ellis@randatmail.com', 'shift': 'Afternoon'}, { 'day': 3, 'resource': 'm.ellis@randatmail.com', 'shift': 'Night'}, { 'day': 5, 'resource': 'm.ellis@randatmail.com', 'shift': 'Morning'}, { 'day': 6, 'resource': 'm.ellis@randatmail.com', 'shift': 'Mixed'}, { 'day': 1, 'resource': 'b.campbell@randatmail.com', 'shift': 'Morning'}, { 'day': 2, 'resource': 'b.campbell@randatmail.com', 'shift': 'Morning'}, { 'day': 3, 'resource': 'b.campbell@randatmail.com', 'shift': 'Morning'}, { 'day': 4, 'resource': 'b.campbell@randatmail.com', 'shift': 'Mixed'}, { 'day': 5, 'resource': 'b.campbell@randatmail.com', 'shift': 'Mixed'}, { 'day': 6, 'resource': 'b.campbell@randatmail.com', 'shift': 'Morning'}, { 'day': 0, 'resource': 's.richards@randatmail.com', 'shift': 'Afternoon'}, { 'day': 1, 'resource': 's.richards@randatmail.com', 'shift': 'Morning'}, { 'day': 2, 'resource': 's.richards@randatmail.com', 'shift': 'Afternoon'}, { 'day': 3, 'resource': 's.richards@randatmail.com', 'shift': 'Night'}, { 'day': 5, 'resource': 's.richards@randatmail.com', 'shift': 'Morning'}, { 'day': 6, 'resource': 's.richards@randatmail.com', 'shift': 'Morning'}, { 'day': 0, 'resource': 'j.evans@randatmail.com', 'shift': 'Afternoon'}, { 'day': 1, 'resource': 'j.evans@randatmail.com', 'shift': 'Mixed'}, { 'day': 2, 'resource': 'j.evans@randatmail.com', 'shift': 'Night'}, { 'day': 4, 'resource': 'j.evans@randatmail.com', 'shift': 'Morning'}, { 'day': 5, 'resource': 'j.evans@randatmail.com', 'shift': 'Mixed'}, { 'day': 6, 'resource': 'j.evans@randatmail.com', 'shift': 'Afternoon'}, { 'day': 0, 'resource': 's.brooks@randatmail.com', 'shift': 'Afternoon'}, { 'day': 1, 'resource': 's.brooks@randatmail.com', 'shift': 'Afternoon'}, { 'day': 2, 'resource': 's.brooks@randatmail.com', 'shift': 'Night'}, { 'day': 4, 'resource': 's.brooks@randatmail.com', 'shift': 'Afternoon'}, { 'day': 5, 'resource': 's.brooks@randatmail.com', 'shift': 'Afternoon'}, { 'day': 6, 'resource': 's.brooks@randatmail.com', 'shift': 'Morning'}, { 'day': 0, 'resource': 'a.montgomery@randatmail.com', 'shift': 'Morning'}, { 'day': 1, 'resource': 'a.montgomery@randatmail.com', 'shift': 'Mixed'}, { 'day': 2, 'resource': 'a.montgomery@randatmail.com', 'shift': 'Morning'}, { 'day': 3, 'resource': 'a.montgomery@randatmail.com', 'shift': 'Afternoon'}, { 'day': 4, 'resource': 'a.montgomery@randatmail.com', 'shift': 'Night'}, { 'day': 6, 'resource': 'a.montgomery@randatmail.com', 'shift': 'Mixed'}, { 'day': 0, 'resource': 'c.hunt@randatmail.com', 'shift': 'Morning'}, { 'day': 1, 'resource': 'c.hunt@randatmail.com', 'shift': 'Morning'}, { 'day': 2, 'resource': 'c.hunt@randatmail.com', 'shift': 'Mixed'}, { 'day': 3, 'resource': 'c.hunt@randatmail.com', 'shift': 'Afternoon'}, { 'day': 4, 'resource': 'c.hunt@randatmail.com', 'shift': 'Night'}, { 'day': 6, 'resource': 'c.hunt@randatmail.com', 'shift': 'Morning'}, { 'day': 0, 'resource': 'v.owens@randatmail.com', 'shift': 'Mixed'}, { 'day': 1, 'resource': 'v.owens@randatmail.com', 'shift': 'Morning'}, { 'day': 2, 'resource': 'v.owens@randatmail.com', 'shift': 'Mixed'}, { 'day': 3, 'resource': 'v.owens@randatmail.com', 'shift': 'Night'}, { 'day': 5, 'resource': 'v.owens@randatmail.com', 'shift': 'Mixed'}, { 'day': 6, 'resource': 'v.owens@randatmail.com', 'shift': 'Mixed'}, { 'day': 0, 'resource': 'a.brown@randatmail.com', 'shift': 'Mixed'}, { 'day': 1, 'resource': 'a.brown@randatmail.com', 'shift': 'Afternoon'}, { 'day': 2, 'resource': 'a.brown@randatmail.com', 'shift': 'Afternoon'}, { 'day': 3, 'resource': 'a.brown@randatmail.com', 'shift': 'Morning'}, { 'day': 4, 'resource': 'a.brown@randatmail.com', 'shift': 'Night'}, { 'day': 6, 'resource': 'a.brown@randatmail.com', 'shift': 'Morning'}, { 'day': 0, 'resource': 'r.armstrong@randatmail.com', 'shift': 'Mixed'}, { 'day': 1, 'resource': 'r.armstrong@randatmail.com', 'shift': 'Morning'}, { 'day': 2, 'resource': 'r.armstrong@randatmail.com', 'shift': 'Afternoon'}, { 'day': 3, 'resource': 'r.armstrong@randatmail.com', 'shift': 'Night'}, { 'day': 5, 'resource': 'r.armstrong@randatmail.com', 'shift': 'Morning'}, { 'day': 6, 'resource': 'r.armstrong@randatmail.com', 'shift': 'Morning'}, { 'day': 0, 'resource': 'm.murray@randatmail.com', 'shift': 'Mixed'}, { 'day': 1, 'resource': 'm.murray@randatmail.com', 'shift': 'Afternoon'}, { 'day': 2, 'resource': 'm.murray@randatmail.com', 'shift': 'Morning'}, { 'day': 3, 'resource': 'm.murray@randatmail.com', 'shift': 'Night'}, { 'day': 5, 'resource': 'm.murray@randatmail.com', 'shift': 'Afternoon'}, { 'day': 6, 'resource': 'm.murray@randatmail.com', 'shift': 'Mixed'}, { 'day': 0, 'resource': 'b.evans@randatmail.com', 'shift': 'Afternoon'}, { 'day': 1, 'resource': 'b.evans@randatmail.com', 'shift': 'Afternoon'}, { 'day': 2, 'resource': 'b.evans@randatmail.com', 'shift': 'Afternoon'}, { 'day': 3, 'resource': 'b.evans@randatmail.com', 'shift': 'Morning'}, { 'day': 4, 'resource': 'b.evans@randatmail.com', 'shift': 'Morning'}, { 'day': 5, 'resource': 'b.evans@randatmail.com', 'shift': 'Night'}, { 'day': 0, 'resource': 'm.brown@randatmail.com', 'shift': 'Morning'}, { 'day': 1, 'resource': 'm.brown@randatmail.com', 'shift': 'Afternoon'}, { 'day': 2, 'resource': 'm.brown@randatmail.com', 'shift': 'Morning'}, { 'day': 3, 'resource': 'm.brown@randatmail.com', 'shift': 'Afternoon'}, { 'day': 4, 'resource': 'm.brown@randatmail.com', 'shift': 'Night'}, { 'day': 6, 'resource': 'm.brown@randatmail.com', 'shift': 'Morning'}, { 'day': 0, 'resource': 's.thompson@randatmail.com', 'shift': 'Mixed'}, { 'day': 1, 'resource': 's.thompson@randatmail.com', 'shift': 'Afternoon'}, { 'day': 2, 'resource': 's.thompson@randatmail.com', 'shift': 'Morning'}, { 'day': 3, 'resource': 's.thompson@randatmail.com', 'shift': 'Night'}, { 'day': 5, 'resource': 's.thompson@randatmail.com', 'shift': 'Morning'}, { 'day': 6, 'resource': 's.thompson@randatmail.com', 'shift': 'Mixed'}, { 'day': 0, 'resource': 'a.ryan@randatmail.com', 'shift': 'Afternoon'}, { 'day': 1, 'resource': 'a.ryan@randatmail.com', 'shift': 'Night'}, { 'day': 3, 'resource': 'a.ryan@randatmail.com', 'shift': 'Afternoon'}, { 'day': 4, 'resource': 'a.ryan@randatmail.com', 'shift': 'Mixed'}, { 'day': 5, 'resource': 'a.ryan@randatmail.com', 'shift': 'Mixed'}, { 'day': 6, 'resource': 'a.ryan@randatmail.com', 'shift': 'Mixed'}, { 'day': 0, 'resource': 'r.carter@randatmail.com', 'shift': 'Mixed'}, { 'day': 1, 'resource': 'r.carter@randatmail.com', 'shift': 'Night'}, { 'day': 3, 'resource': 'r.carter@randatmail.com', 'shift': 'Afternoon'}, { 'day': 4, 'resource': 'r.carter@randatmail.com', 'shift': 'Morning'}, { 'day': 5, 'resource': 'r.carter@randatmail.com', 'shift': 'Morning'}, { 'day': 6, 'resource': 'r.carter@randatmail.com', 'shift': 'Mixed'}, { 'day': 1, 'resource': 'j.payne@randatmail.com', 'shift': 'Morning'}, { 'day': 2, 'resource': 'j.payne@randatmail.com', 'shift': 'Afternoon'}, { 'day': 3, 'resource': 'j.payne@randatmail.com', 'shift': 'Afternoon'}, { 'day': 4, 'resource': 'j.payne@randatmail.com', 'shift': 'Morning'}, { 'day': 5, 'resource': 'j.payne@randatmail.com', 'shift': 'Mixed'}, { 'day': 6, 'resource': 'j.payne@randatmail.com', 'shift': 'Morning'}, { 'day': 0, 'resource': 's.perkins@randatmail.com', 'shift': 'Afternoon'}, { 'day': 1, 'resource': 's.perkins@randatmail.com', 'shift': 'Afternoon'}, { 'day': 2, 'resource': 's.perkins@randatmail.com', 'shift': 'Morning'}, { 'day': 3, 'resource': 's.perkins@randatmail.com', 'shift': 'Mixed'}, { 'day': 4, 'resource': 's.perkins@randatmail.com', 'shift': 'Morning'}, { 'day': 5, 'resource': 's.perkins@randatmail.com', 'shift': 'Night'}, { 'day': 0, 'resource': 't.west@randatmail.com', 'shift': 'Mixed'}, { 'day': 1, 'resource': 't.west@randatmail.com', 'shift': 'Morning'}, { 'day': 2, 'resource': 't.west@randatmail.com', 'shift': 'Mixed'}, { 'day': 3, 'resource': 't.west@randatmail.com', 'shift': 'Morning'}, { 'day': 4, 'resource': 't.west@randatmail.com', 'shift': 'Morning'}, { 'day': 5, 'resource': 't.west@randatmail.com', 'shift': 'Night'}, { 'day': 0, 'resource': 'd.stevens@randatmail.com', 'shift': 'Mixed'}, { 'day': 1, 'resource': 'd.stevens@randatmail.com', 'shift': 'Night'}, { 'day': 3, 'resource': 'd.stevens@randatmail.com', 'shift': 'Morning'}, { 'day': 4, 'resource': 'd.stevens@randatmail.com', 'shift': 'Mixed'}, { 'day': 5, 'resource': 'd.stevens@randatmail.com', 'shift': 'Mixed'}, { 'day': 6, 'resource': 'd.stevens@randatmail.com', 'shift': 'Afternoon'}, { 'day': 0, 'resource': 'l.gibson@randatmail.com', 'shift': 'Morning'}, { 'day': 1, 'resource': 'l.gibson@randatmail.com', 'shift': 'Morning'}, { 'day': 2, 'resource': 'l.gibson@randatmail.com', 'shift': 'Night'}, { 'day': 4, 'resource': 'l.gibson@randatmail.com', 'shift': 'Morning'}, { 'day': 5, 'resource': 'l.gibson@randatmail.com', 'shift': 'Mixed'}, { 'day': 6, 'resource': 'l.gibson@randatmail.com', 'shift': 'Mixed'}, { 'day': 0, 'resource': 'm.crawford@randatmail.com', 'shift': 'Mixed'}, { 'day': 1, 'resource': 'm.crawford@randatmail.com', 'shift': 'Mixed'}, { 'day': 2, 'resource': 'm.crawford@randatmail.com', 'shift': 'Mixed'}, { 'day': 3, 'resource': 'm.crawford@randatmail.com', 'shift': 'Mixed'}, { 'day': 4, 'resource': 'm.crawford@randatmail.com', 'shift': 'Afternoon'}, { 'day': 5, 'resource': 'm.crawford@randatmail.com', 'shift': 'Night'}, { 'day': 0, 'resource': 'a.barnes@randatmail.com', 'shift': 'Mixed'}, { 'day': 1, 'resource': 'a.barnes@randatmail.com', 'shift': 'Afternoon'}, { 'day': 2, 'resource': 'a.barnes@randatmail.com', 'shift': 'Mixed'}, { 'day': 3, 'resource': 'a.barnes@randatmail.com', 'shift': 'Morning'}, { 'day': 4, 'resource': 'a.barnes@randatmail.com', 'shift': 'Afternoon'}, { 'day': 5, 'resource': 'a.barnes@randatmail.com', 'shift': 'Night'}, { 'day': 0, 'resource': 'm.howard@randatmail.com', 'shift': 'Afternoon'}, { 'day': 1, 'resource': 'm.howard@randatmail.com', 'shift': 'Morning'}, { 'day': 2, 'resource': 'm.howard@randatmail.com', 'shift': 'Night'}, { 'day': 4, 'resource': 'm.howard@randatmail.com', 'shift': 'Afternoon'}, { 'day': 5, 'resource': 'm.howard@randatmail.com', 'shift': 'Mixed'}, { 'day': 6, 'resource': 'm.howard@randatmail.com', 'shift': 'Night'}, { 'day': 0, 'resource': 't.chapman@randatmail.com', 'shift': 'Afternoon'}, { 'day': 1, 'resource': 't.chapman@randatmail.com', 'shift': 'Afternoon'}, { 'day': 2, 'resource': 't.chapman@randatmail.com', 'shift': 'Morning'}, { 'day': 3, 'resource': 't.chapman@randatmail.com', 'shift': 'Morning'}, { 'day': 4, 'resource': 't.chapman@randatmail.com', 'shift': 'Mixed'}, { 'day': 5, 'resource': 't.chapman@randatmail.com', 'shift': 'Night'}, { 'day': 0, 'resource': 's.harris@randatmail.com', 'shift': 'Mixed'}, { 'day': 1, 'resource': 's.harris@randatmail.com', 'shift': 'Morning'}, { 'day': 2, 'resource': 's.harris@randatmail.com', 'shift': 'Afternoon'}, { 'day': 3, 'resource': 's.harris@randatmail.com', 'shift': 'Night'}, { 'day': 5, 'resource': 's.harris@randatmail.com', 'shift': 'Morning'}, { 'day': 6, 'resource': 's.harris@randatmail.com', 'shift': 'Mixed'}, { 'day': 0, 'resource': 'a.farrell@randatmail.com', 'shift': 'Afternoon'}, { 'day': 1, 'resource': 'a.farrell@randatmail.com', 'shift': 'Afternoon'}, { 'day': 2, 'resource': 'a.farrell@randatmail.com', 'shift': 'Afternoon'}, { 'day': 3, 'resource': 'a.farrell@randatmail.com', 'shift': 'Night'}, { 'day': 5, 'resource': 'a.farrell@randatmail.com', 'shift': 'Afternoon'}, { 'day': 6, 'resource': 'a.farrell@randatmail.com', 'shift': 'Night'}, { 'day': 0, 'resource': 'd.douglas@randatmail.com', 'shift': 'Mixed'}, { 'day': 1, 'resource': 'd.douglas@randatmail.com', 'shift': 'Morning'}, { 'day': 2, 'resource': 'd.douglas@randatmail.com', 'shift': 'Mixed'}, { 'day': 3, 'resource': 'd.douglas@randatmail.com', 'shift': 'Night'}, { 'day': 5, 'resource': 'd.douglas@randatmail.com', 'shift': 'Morning'}, { 'day': 6, 'resource': 'd.douglas@randatmail.com', 'shift': 'Mixed'}, { 'day': 0, 'resource': 'a.douglas@randatmail.com', 'shift': 'Mixed'}, { 'day': 1, 'resource': 'a.douglas@randatmail.com', 'shift': 'Mixed'}, { 'day': 2, 'resource': 'a.douglas@randatmail.com', 'shift': 'Mixed'}, { 'day': 3, 'resource': 'a.douglas@randatmail.com', 'shift': 'Mixed'}, { 'day': 4, 'resource': 'a.douglas@randatmail.com', 'shift': 'Night'}, { 'day': 6, 'resource': 'a.douglas@randatmail.com', 'shift': 'Morning'}, { 'day': 0, 'resource': 'j.cole@randatmail.com', 'shift': 'Night'}, { 'day': 2, 'resource': 'j.cole@randatmail.com', 'shift': 'Mixed'}, { 'day': 3, 'resource': 'j.cole@randatmail.com', 'shift': 'Mixed'}, { 'day': 4, 'resource': 'j.cole@randatmail.com', 'shift': 'Afternoon'}, { 'day': 5, 'resource': 'j.cole@randatmail.com', 'shift': 'Morning'}, { 'day': 6, 'resource': 'j.cole@randatmail.com', 'shift': 'Afternoon'}, { 'day': 0, 'resource': 'v.myers@randatmail.com', 'shift': 'Mixed'}, { 'day': 1, 'resource': 'v.myers@randatmail.com', 'shift': 'Mixed'}, { 'day': 2, 'resource': 'v.myers@randatmail.com', 'shift': 'Mixed'}, { 'day': 3, 'resource': 'v.myers@randatmail.com', 'shift': 'Afternoon'}, { 'day': 4, 'resource': 'v.myers@randatmail.com', 'shift': 'Afternoon'}, { 'day': 5, 'resource': 'v.myers@randatmail.com', 'shift': 'Night'}, { 'day': 0, 'resource': 'l.owens@randatmail.com', 'shift': 'Mixed'}, { 'day': 1, 'resource': 'l.owens@randatmail.com', 'shift': 'Night'}, { 'day': 3, 'resource': 'l.owens@randatmail.com', 'shift': 'Afternoon'}, { 'day': 4, 'resource': 'l.owens@randatmail.com', 'shift': 'Mixed'}, { 'day': 5, 'resource': 'l.owens@randatmail.com', 'shift': 'Mixed'}, { 'day': 6, 'resource': 'l.owens@randatmail.com', 'shift': 'Morning'}, { 'day': 0, 'resource': 'h.robinson@randatmail.com', 'shift': 'Night'}, { 'day': 2, 'resource': 'h.robinson@randatmail.com', 'shift': 'Mixed'}, { 'day': 3, 'resource': 'h.robinson@randatmail.com', 'shift': 'Mixed'}, { 'day': 4, 'resource': 'h.robinson@randatmail.com', 'shift': 'Afternoon'}, { 'day': 5, 'resource': 'h.robinson@randatmail.com', 'shift': 'Mixed'}, { 'day': 6, 'resource': 'h.robinson@randatmail.com', 'shift': 'Morning'}, { 'day': 0, 'resource': 's.spencer@randatmail.com', 'shift': 'Mixed'}, { 'day': 1, 'resource': 's.spencer@randatmail.com', 'shift': 'Mixed'}, { 'day': 2, 'resource': 's.spencer@randatmail.com', 'shift': 'Mixed'}, { 'day': 3, 'resource': 's.spencer@randatmail.com', 'shift': 'Afternoon'}, { 'day': 4, 'resource': 's.spencer@randatmail.com', 'shift': 'Night'}, { 'day': 6, 'resource': 's.spencer@randatmail.com', 'shift': 'Afternoon'}, { 'day': 0, 'resource': 'v.brooks@randatmail.com', 'shift': 'Morning'}, { 'day': 1, 'resource': 'v.brooks@randatmail.com', 'shift': 'Mixed'}, { 'day': 2, 'resource': 'v.brooks@randatmail.com', 'shift': 'Mixed'}, { 'day': 3, 'resource': 'v.brooks@randatmail.com', 'shift': 'Night'}, { 'day': 5, 'resource': 'v.brooks@randatmail.com', 'shift': 'Afternoon'}, { 'day': 6, 'resource': 'v.brooks@randatmail.com', 'shift': 'Afternoon'}, { 'day': 0, 'resource': 'h.turner@randatmail.com', 'shift': 'Mixed'}, { 'day': 1, 'resource': 'h.turner@randatmail.com', 'shift': 'Mixed'}, { 'day': 2, 'resource': 'h.turner@randatmail.com', 'shift': 'Mixed'}, { 'day': 3, 'resource': 'h.turner@randatmail.com', 'shift': 'Mixed'}, { 'day': 4, 'resource': 'h.turner@randatmail.com', 'shift': 'Afternoon'}, { 'day': 5, 'resource': 'h.turner@randatmail.com', 'shift': 'Night'}, { 'day': 0, 'resource': 'e.elliott@randatmail.com', 'shift': 'Mixed'}, { 'day': 1, 'resource': 'e.elliott@randatmail.com', 'shift': 'Night'}, { 'day': 3, 'resource': 'e.elliott@randatmail.com', 'shift': 'Mixed'}, { 'day': 4, 'resource': 'e.elliott@randatmail.com', 'shift': 'Morning'}, { 'day': 5, 'resource': 'e.elliott@randatmail.com', 'shift': 'Afternoon'}, { 'day': 6, 'resource': 'e.elliott@randatmail.com', 'shift': 'Mixed'}, { 'day': 0, 'resource': 'a.adams@randatmail.com', 'shift': 'Mixed'}, { 'day': 1, 'resource': 'a.adams@randatmail.com', 'shift': 'Mixed'}, { 'day': 2, 'resource': 'a.adams@randatmail.com', 'shift': 'Mixed'}, { 'day': 3, 'resource': 'a.adams@randatmail.com', 'shift': 'Night'}, { 'day': 5, 'resource': 'a.adams@randatmail.com', 'shift': 'Afternoon'}, { 'day': 6, 'resource': 'a.adams@randatmail.com', 'shift': 'Mixed'}, { 'day': 0, 'resource': 'm.higgins@randatmail.com', 'shift': 'Afternoon'}, { 'day': 1, 'resource': 'm.higgins@randatmail.com', 'shift': 'Mixed'}, { 'day': 2, 'resource': 'm.higgins@randatmail.com', 'shift': 'Mixed'}, { 'day': 3, 'resource': 'm.higgins@randatmail.com', 'shift': 'Night'}, { 'day': 5, 'resource': 'm.higgins@randatmail.com', 'shift': 'Mixed'}, { 'day': 6, 'resource': 'm.higgins@randatmail.com', 'shift': 'Night'}, { 'day': 1, 'resource': 'j.cole@randatmail.com', 'shift': 'Mixed'}, { 'day': 2, 'resource': 'j.cole@randatmail.com', 'shift': 'Mixed'}, { 'day': 3, 'resource': 'j.cole@randatmail.com', 'shift': 'Afternoon'}, { 'day': 4, 'resource': 'j.cole@randatmail.com', 'shift': 'Mixed'}, { 'day': 5, 'resource': 'j.cole@randatmail.com', 'shift': 'Mixed'}, { 'day': 6, 'resource': 'j.cole@randatmail.com', 'shift': 'Morning'}, { 'day': 0, 'resource': 'm.ryan@randatmail.com', 'shift': 'Night'}, { 'day': 2, 'resource': 'm.ryan@randatmail.com', 'shift': 'Mixed'}, { 'day': 3, 'resource': 'm.ryan@randatmail.com', 'shift': 'Morning'}, { 'day': 4, 'resource': 'm.ryan@randatmail.com', 'shift': 'Mixed'}, { 'day': 5, 'resource': 'm.ryan@randatmail.com', 'shift': 'Mixed'}, { 'day': 6, 'resource': 'm.ryan@randatmail.com', 'shift': 'Mixed'}, { 'day': 0, 'resource': 'l.wilson@randatmail.com', 'shift': 'Morning'}, { 'day': 1, 'resource': 'l.wilson@randatmail.com', 'shift': 'Mixed'}, { 'day': 2, 'resource': 'l.wilson@randatmail.com', 'shift': 'Mixed'}, { 'day': 3, 'resource': 'l.wilson@randatmail.com', 'shift': 'Night'}, { 'day': 5, 'resource': 'l.wilson@randatmail.com', 'shift': 'Mixed'}, { 'day': 6, 'resource': 'l.wilson@randatmail.com', 'shift': 'Afternoon'}, { 'day': 0, 'resource': 'j.higgins@randatmail.com', 'shift': 'Morning'}, { 'day': 1, 'resource': 'j.higgins@randatmail.com', 'shift': 'Mixed'}, { 'day': 2, 'resource': 'j.higgins@randatmail.com', 'shift': 'Mixed'}, { 'day': 3, 'resource': 'j.higgins@randatmail.com', 'shift': 'Night'}, { 'day': 5, 'resource': 'j.higgins@randatmail.com', 'shift': 'Afternoon'}, { 'day': 6, 'resource': 'j.higgins@randatmail.com', 'shift': 'Mixed'}, { 'day': 0, 'resource': 'v.ryan@randatmail.com', 'shift': 'Night'}, { 'day': 2, 'resource': 'v.ryan@randatmail.com', 'shift': 'Mixed'}, { 'day': 3, 'resource': 'v.ryan@randatmail.com', 'shift': 'Mixed'}, { 'day': 4, 'resource': 'v.ryan@randatmail.com', 'shift': 'Mixed'}, { 'day': 5, 'resource': 'v.ryan@randatmail.com', 'shift': 'Afternoon'}, { 'day': 6, 'resource': 'v.ryan@randatmail.com', 'shift': 'Mixed'}, { 'day': 0, 'resource': 'c.perry@randatmail.com', 'shift': 'Night'}, { 'day': 2, 'resource': 'c.perry@randatmail.com', 'shift': 'Afternoon'}, { 'day': 3, 'resource': 'c.perry@randatmail.com', 'shift': 'Mixed'}, { 'day': 4, 'resource': 'c.perry@randatmail.com', 'shift': 'Mixed'}, { 'day': 5, 'resource': 'c.perry@randatmail.com', 'shift': 'Afternoon'}, { 'day': 6, 'resource': 'c.perry@randatmail.com', 'shift': 'Afternoon'}, { 'day': 0, 'resource': 'c.wright@randatmail.com', 'shift': 'Night'}, { 'day': 2, 'resource': 'c.wright@randatmail.com', 'shift': 'Mixed'}, { 'day': 3, 'resource': 'c.wright@randatmail.com', 'shift': 'Mixed'}, { 'day': 4, 'resource': 'c.wright@randatmail.com', 'shift': 'Mixed'}, { 'day': 5, 'resource': 'c.wright@randatmail.com', 'shift': 'Afternoon'}, { 'day': 6, 'resource': 'c.wright@randatmail.com', 'shift': 'Mixed'}, { 'day': 0, 'resource': 'f.myers@randatmail.com', 'shift': 'Night'}, { 'day': 2, 'resource': 'f.myers@randatmail.com', 'shift': 'Mixed'}, { 'day': 3, 'resource': 'f.myers@randatmail.com', 'shift': 'Morning'}, { 'day': 4, 'resource': 'f.myers@randatmail.com', 'shift': 'Morning'}, { 'day': 5, 'resource': 'f.myers@randatmail.com', 'shift': 'Mixed'}, { 'day': 6, 'resource': 'f.myers@randatmail.com', 'shift': 'Mixed'}, { 'day': 0, 'resource': 'c.allen@randatmail.com', 'shift': 'Morning'}, { 'day': 1, 'resource': 'c.allen@randatmail.com', 'shift': 'Mixed'}, { 'day': 2, 'resource': 'c.allen@randatmail.com', 'shift': 'Mixed'}, { 'day': 3, 'resource': 'c.allen@randatmail.com', 'shift': 'Mixed'}, { 'day': 4, 'resource': 'c.allen@randatmail.com', 'shift': 'Night'}, { 'day': 6, 'resource': 'c.allen@randatmail.com', 'shift': 'Mixed'}, { 'day': 0, 'resource': 'c.stevens@randatmail.com', 'shift': 'Mixed'}, { 'day': 1, 'resource': 'c.stevens@randatmail.com', 'shift': 'Night'}, { 'day': 3, 'resource': 'c.stevens@randatmail.com', 'shift': 'Mixed'}, { 'day': 4, 'resource': 'c.stevens@randatmail.com', 'shift': 'Mixed'}, { 'day': 5, 'resource': 'c.stevens@randatmail.com', 'shift': 'Mixed'}, { 'day': 6, 'resource': 'c.stevens@randatmail.com', 'shift': 'Night'}, { 'day': 0, 'resource': 'c.campbell@randatmail.com', 'shift': 'Afternoon'}, { 'day': 1, 'resource': 'c.campbell@randatmail.com', 'shift': 'Afternoon'}, { 'day': 2, 'resource': 'c.campbell@randatmail.com', 'shift': 'Afternoon'}, { 'day': 3, 'resource': 'c.campbell@randatmail.com', 'shift': 'Afternoon'}, { 'day': 4, 'resource': 'c.campbell@randatmail.com', 'shift': 'Afternoon'}, { 'day': 5, 'resource': 'c.campbell@randatmail.com', 'shift': 'Afternoon'}, { 'day': 0, 'resource': 'd.taylor@randatmail.com', 'shift': 'Night'}, { 'day': 2, 'resource': 'd.taylor@randatmail.com', 'shift': 'Mixed'}, { 'day': 3, 'resource': 'd.taylor@randatmail.com', 'shift': 'Mixed'}, { 'day': 4, 'resource': 'd.taylor@randatmail.com', 'shift': 'Morning'}, { 'day': 5, 'resource': 'd.taylor@randatmail.com', 'shift': 'Mixed'}, { 'day': 6, 'resource': 'd.taylor@randatmail.com', 'shift': 'Night'}, { 'day': 0, 'resource': 'h.myers@randatmail.com', 'shift': 'Mixed'}, { 'day': 1, 'resource': 'h.myers@randatmail.com', 'shift': 'Night'}, { 'day': 3, 'resource': 'h.myers@randatmail.com', 'shift': 'Mixed'}, { 'day': 4, 'resource': 'h.myers@randatmail.com', 'shift': 'Morning'}, { 'day': 5, 'resource': 'h.myers@randatmail.com', 'shift': 'Mixed'}, { 'day': 6, 'resource': 'h.myers@randatmail.com', 'shift': 'Night'}], 'resting_days': 55, 'resting_resource': [ {'day': 3, 'resource': 'e.johnston@randatmail.com'}, {'day': 1, 'resource': 'd.harper@randatmail.com'}, {'day': 4, 'resource': 'm.hawkins@randatmail.com'}, {'day': 4, 'resource': 'm.ellis@randatmail.com'}, {'day': 0, 'resource': 'b.campbell@randatmail.com'}, {'day': 4, 'resource': 's.richards@randatmail.com'}, {'day': 3, 'resource': 'j.evans@randatmail.com'}, {'day': 3, 'resource': 's.brooks@randatmail.com'}, {'day': 5, 'resource': 'a.montgomery@randatmail.com'}, {'day': 5, 'resource': 'c.hunt@randatmail.com'}, {'day': 4, 'resource': 'v.owens@randatmail.com'}, {'day': 5, 'resource': 'a.brown@randatmail.com'}, {'day': 4, 'resource': 'r.armstrong@randatmail.com'}, {'day': 4, 'resource': 'm.murray@randatmail.com'}, {'day': 6, 'resource': 'b.evans@randatmail.com'}, {'day': 5, 'resource': 'm.brown@randatmail.com'}, {'day': 4, 'resource': 's.thompson@randatmail.com'}, {'day': 2, 'resource': 'a.ryan@randatmail.com'}, {'day': 2, 'resource': 'r.carter@randatmail.com'}, {'day': 0, 'resource': 'j.payne@randatmail.com'}, {'day': 6, 'resource': 's.perkins@randatmail.com'}, {'day': 6, 'resource': 't.west@randatmail.com'}, {'day': 2, 'resource': 'd.stevens@randatmail.com'}, {'day': 3, 'resource': 'l.gibson@randatmail.com'}, {'day': 6, 'resource': 'm.crawford@randatmail.com'}, {'day': 6, 'resource': 'a.barnes@randatmail.com'}, {'day': 3, 'resource': 'm.howard@randatmail.com'}, {'day': 6, 'resource': 't.chapman@randatmail.com'}, {'day': 4, 'resource': 's.harris@randatmail.com'}, {'day': 4, 'resource': 'a.farrell@randatmail.com'}, {'day': 4, 'resource': 'd.douglas@randatmail.com'}, {'day': 5, 'resource': 'a.douglas@randatmail.com'}, {'day': 1, 'resource': 'j.cole@randatmail.com'}, {'day': 6, 'resource': 'v.myers@randatmail.com'}, {'day': 2, 'resource': 'l.owens@randatmail.com'}, {'day': 1, 'resource': 'h.robinson@randatmail.com'}, {'day': 5, 'resource': 's.spencer@randatmail.com'}, {'day': 4, 'resource': 'v.brooks@randatmail.com'}, {'day': 6, 'resource': 'h.turner@randatmail.com'}, {'day': 2, 'resource': 'e.elliott@randatmail.com'}, {'day': 4, 'resource': 'a.adams@randatmail.com'}, {'day': 4, 'resource': 'm.higgins@randatmail.com'}, {'day': 0, 'resource': 'j.cole@randatmail.com'}, {'day': 1, 'resource': 'm.ryan@randatmail.com'}, {'day': 4, 'resource': 'l.wilson@randatmail.com'}, {'day': 4, 'resource': 'j.higgins@randatmail.com'}, {'day': 1, 'resource': 'v.ryan@randatmail.com'}, {'day': 1, 'resource': 'c.perry@randatmail.com'}, {'day': 1, 'resource': 'c.wright@randatmail.com'}, {'day': 1, 'resource': 'f.myers@randatmail.com'}, {'day': 5, 'resource': 'c.allen@randatmail.com'}, {'day': 2, 'resource': 'c.stevens@randatmail.com'}, {'day': 6, 'resource': 'c.campbell@randatmail.com'}, {'day': 1, 'resource': 'd.taylor@randatmail.com'}, {'day': 2, 'resource': 'h.myers@randatmail.com'}], 'shifted_hours': 2388, 'status': 'OPTIMAL', 'total_resources': 55, 'total_shifts': 330}