Nurse Scheduling API Reference
Data
Data model for NurseScheduling use case.
NurseSchedulingData
Bases: UcData
Data for the Nurse Scheduling Problem use case.
This class encapsulates all necessary information to define and solve a Nurse Scheduling problem instance. The unified formulation supports both 2-shift and 3-shift systems. Given a set of nurses and shifts, the problem creates rotating rosters that satisfy workforce requirements while respecting nurse preferences and day-off requests.
Attributes:
-
name(Literal['nurse_scheduling']) –A constant identifier for this data type, always set to "nurse_scheduling". Used for registration and type identification in the use case registry.
-
n_nurses(int) –Number of nurses available for scheduling.
-
n_shifts(int) –Number of shifts in the schedule.
-
workforce(NumPyArray) –Required workforce W(d) for each shift d. 1D float array of length n_shifts.
-
effort(NumPyArray) –Effort level E(n) for each nurse n. 1D float array of length n_nurses.
-
max_shifts(NumPyArray) –Maximum number of (weighted) shifts F(n) each nurse can work. 1D int array of length n_nurses.
-
shift_weight(NumPyArray) –Weight for each shift indicating how much it "counts" toward a nurse's maximum shift allowance (used in constraint C3). A weight of 2.0 means the shift counts double — e.g., a night shift with weight 2.0 uses two of a nurse's allowed shifts. 1D float array of length n_shifts.
-
day_off_priority(NumPyArray) –Priority matrix g(n,d) for day-off requests. 2D float array of shape (n_nurses, n_shifts). 0 = no request, higher = stronger request.
Examples:
Create a simple nurse scheduling instance:
>>> data = NurseSchedulingData(
... n_nurses=3,
... n_shifts=6,
... workforce=np.array([2.0, 2.0, 2.0, 2.0, 2.0, 2.0]),
... effort=np.array([1.0, 1.0, 1.0]),
... max_shifts=np.array([3, 3, 3]),
... shift_weight=np.array([1.0, 1.0, 1.0, 1.0, 1.0, 1.0]),
... day_off_priority=np.zeros((3, 6)),
... )
plot(*, ax: Axes | None = None) -> Axes
Plot workforce requirements and shift weights.
Shows a bar chart of workforce requirements per shift with shift weights overlaid as a line.
Parameters:
-
ax(Axes | None, default:None) –Matplotlib axes to draw on. Creates a new figure if
None.
Returns:
-
Axes–The axes with the plot.
to_string() -> str
from_values(n_nurses: int, n_shifts: int, workforce: np.ndarray | list[float], effort: np.ndarray | list[float], max_shifts: np.ndarray | list[int], shift_weight: np.ndarray | list[float], day_off_priority: np.ndarray | list[list[float]]) -> NurseSchedulingData
staticmethod
Create a NurseSchedulingData instance from explicit values.
Parameters:
-
n_nurses(int) –Number of nurses available for scheduling.
-
n_shifts(int) –Number of shifts in the schedule.
-
workforce(ndarray | list[float]) –Required workforce W(d) for each shift d. 1D array of length n_shifts.
-
effort(ndarray | list[float]) –Effort level E(n) for each nurse n. 1D array of length n_nurses.
-
max_shifts(ndarray | list[int]) –Maximum number of (weighted) shifts F(n) each nurse can work. 1D array of length n_nurses.
-
shift_weight(ndarray | list[float]) –Weight for each shift. 1D array of length n_shifts.
-
day_off_priority(ndarray | list[list[float]]) –Priority matrix g(n,d) for day-off requests. 2D array of shape (n_nurses, n_shifts).
Returns:
-
NurseSchedulingData–A NurseSchedulingData instance with the given values.
generate_random(n_nurses: int = 10, n_shifts: int = 14, shift_system: str = 'two_shift', seed: int | None = None) -> NurseSchedulingData
staticmethod
Generate a random Nurse Scheduling instance.
Parameters:
-
n_nurses(int, default:10) –Number of nurses, by default 10.
-
n_shifts(int, default:14) –Number of shifts, by default 14.
-
shift_system(str, default:'two_shift') –Either "two_shift" or "three_shift", by default "two_shift". Controls how shift weights are generated.
-
seed(int | None, default:None) –Random seed for reproducibility, by default None.
Returns:
-
NurseSchedulingData–A randomly generated Nurse Scheduling data instance.
Formulation
Formulation for NurseScheduling use case.
NurseSchedulingFormulation
Bases: UcFormulation[NurseSchedulingData, NurseSchedulingSolution]
Constraint-based formulation for Nurse Scheduling Problem.
This formulation uses LunaModel's constraint system to create rotating rosters that satisfy workforce requirements while respecting nurse preferences and day-off requests. Supports both 2-shift and 3-shift systems through unified shift weight parameters.
Mathematical Formulation
Given:
- N nurses with effort levels E(n) and max shifts F(n)
- D shifts with workforce requirements W(d) and weights
- Day-off priority matrix g(n,d)
Decision Variables:
q[n,d] in {0,1} for each nurse n and shift d
q[n,d] = 1 if nurse n is assigned to shift d
Objective:
minimize sum_{n,d} g(n,d) * q[n,d]
(minimize scheduling nurses on their day-off requests)
Constraints:
1. No consecutive shifts:
q[n,d] + q[n,d+1] <= 1 for each nurse n, shift d < D-1
2. Workforce requirement:
sum_n E(n)*q[n,d] >= W(d) for each shift d
3. Max shift count (weighted):
sum_d shift_weight(d)*q[n,d] <= F(n) for each nurse n
References
- Nurse Scheduling Problem: https://en.wikipedia.org/wiki/Nurse_scheduling_problem
to_string(data: NurseSchedulingData) -> str
staticmethod
Print the formulation.
Parameters:
-
data(NurseSchedulingData) –The problem data.
Returns:
-
str–String representation of the formulation.
formulate(data: NurseSchedulingData) -> Model
staticmethod
Formulate the Nurse Scheduling Problem using constraint-based approach.
Creates a constraint-based formulation using binary decision variables for nurse-shift assignments with workforce, consecutive shift, and max shift count constraints.
Parameters:
-
data(NurseSchedulingData) –The Nurse Scheduling instance data.
Returns:
-
Model–A LunaModel ready to be solved.
Raises:
-
EmptyDataError–If there are no nurses or no shifts.
-
InvalidProblemStructureError–If array dimensions do not match the declared sizes.
interpret(solution: Solution, data: NurseSchedulingData) -> NurseSchedulingSolution
staticmethod
Extract solution from solver result.
Extracts the nurse-shift assignments from the solver solution and computes solution metrics including validity checks.
Parameters:
-
solution(Solution) –The solver solution containing variable assignments.
-
data(NurseSchedulingData) –The original Nurse Scheduling instance data.
Returns:
-
NurseSchedulingSolution–A structured solution object with schedule and metrics.
Raises:
-
NoSolutionFoundError–If the solver did not find a solution.
Solution
Solution model for NurseScheduling use case.
NurseSchedulingSolution
Bases: UcSolution
Solution for the Nurse Scheduling Problem.
Attributes:
-
name(Literal['nurse_scheduling']) –Identifier for this solution type.
-
schedule(dict[int, list[int]]) –Maps nurse index to list of assigned shift indices.
-
n_shifts_assigned(int) –Total number of nurse-shift assignments.
-
is_valid(bool) –Whether constraints are satisfied (no consecutive shifts, workforce met).
plot(data: NurseSchedulingData | None = None, *, ax: Axes | None = None) -> Axes
Plot the nurse schedule as a grid.
Shows a heatmap where rows are nurses and columns are shifts. Assigned shifts are highlighted in color.
Parameters:
-
data(NurseSchedulingData | None, default:None) –Problem data. When provided, workforce coverage info is shown.
-
ax(Axes | None, default:None) –Matplotlib axes to draw on. Creates a new figure if
None.
Returns:
-
Axes–The axes with the plot.
to_string() -> str
Instance
Instance model for NurseScheduling use case.
NurseSchedulingInstance
Bases: UcInstance[NurseSchedulingData, NurseSchedulingFormulation, NurseSchedulingSolution]
Instance combining data and formulation for NurseScheduling.
Collection
Collection of NurseScheduling instances.
NurseSchedulingCollection
Bases: UcInstanceCollection[NurseSchedulingInstance]
Collection of Nurse Scheduling Problem instances.
This collection provides methods to generate benchmark instances with various characteristics for testing and evaluation, including random, two-shift, and three-shift system instances.
from_random(min_num_nurses: int | None = None, max_num_nurses: int | None = None, num_instances: int = 1, *, sizes: Sequence[int] | None = None, n_shifts: int = 14, shift_system: str = 'two_shift', seed: int | None = None) -> NurseSchedulingCollection
classmethod
Generate random nurse scheduling instances.
Generates instances with varying nurse counts and random parameters.
Parameters:
-
min_num_nurses(int | None, default:None) –Minimum number of nurses per instance.
-
max_num_nurses(int | None, default:None) –Maximum number of nurses per instance.
-
num_instances(int, default:1) –Number of instances per size, by default 1.
-
n_shifts(int, default:14) –Number of shifts per instance, by default 14.
-
shift_system(str, default:'two_shift') –Either "two_shift" or "three_shift", by default "two_shift".
-
seed(int | None, default:None) –Random seed for reproducibility, by default None.
-
sizes(Sequence[int] | None, default:None) –Explicit sizes to generate, e.g.
[10, 50, 100], instead of a range. Mutually exclusive withmin_num_nurses/max_num_nurses, by default None.
Returns:
-
NurseSchedulingCollection–Collection containing generated instances.
Examples:
from_two_shift(min_num_nurses: int | None = None, max_num_nurses: int | None = None, num_instances: int = 1, *, sizes: Sequence[int] | None = None, n_shifts: int = 14, seed: int | None = None) -> NurseSchedulingCollection
classmethod
Generate 2-shift system nurse scheduling instances.
Shift weights are based on h_1(n)*h_2(d) pattern where alternating shifts have different weights (e.g., day/night).
Parameters:
-
min_num_nurses(int | None, default:None) –Minimum number of nurses per instance.
-
max_num_nurses(int | None, default:None) –Maximum number of nurses per instance.
-
num_instances(int, default:1) –Number of instances per size, by default 1.
-
n_shifts(int, default:14) –Number of shifts per instance, by default 14.
-
seed(int | None, default:None) –Random seed for reproducibility, by default None.
-
sizes(Sequence[int] | None, default:None) –Explicit sizes to generate, e.g.
[10, 50, 100], instead of a range. Mutually exclusive withmin_num_nurses/max_num_nurses, by default None.
Returns:
-
NurseSchedulingCollection–Collection containing 2-shift system instances.
Examples:
from_three_shift(min_num_nurses: int | None = None, max_num_nurses: int | None = None, num_instances: int = 1, *, sizes: Sequence[int] | None = None, n_shifts: int = 21, seed: int | None = None) -> NurseSchedulingCollection
classmethod
Generate 3-shift system nurse scheduling instances.
Shift weights are based on day_type*shift_type pattern: - shift_type: daytime=1.0, early_night=1.5, late_night=2.0 - day_type: weekday=1.0, weekend=2.0
Parameters:
-
min_num_nurses(int | None, default:None) –Minimum number of nurses per instance.
-
max_num_nurses(int | None, default:None) –Maximum number of nurses per instance.
-
num_instances(int, default:1) –Number of instances per size, by default 1.
-
n_shifts(int, default:21) –Number of shifts per instance, by default 21 (7 days * 3 shifts).
-
seed(int | None, default:None) –Random seed for reproducibility, by default None.
-
sizes(Sequence[int] | None, default:None) –Explicit sizes to generate, e.g.
[10, 50, 100], instead of a range. Mutually exclusive withmin_num_nurses/max_num_nurses, by default None.
Returns:
-
NurseSchedulingCollection–Collection containing 3-shift system instances.
Examples:
filter_infeasible(max_runtime: float = 3600, *, quiet: bool = True) -> list[bool]
Drop the instances of this collection that have no feasible solution.
Every instance is formulated and handed to SCIP, which stops as soon as
it finds the first feasible solution. An instance is removed from the
collection when SCIP proves the model infeasible, when no solution turns
up within max_runtime, or when formulating it fails altogether. This
keeps randomly generated instances from breaking a downstream pipeline.
Parameters:
-
max_runtime(float, default:3600) –SCIP time limit per instance in seconds. Must be positive. Defaults to 3600 seconds.
-
quiet(bool, default:True) –Suppress the SCIP solver output.
Returns:
-
list[bool]–Feasibility mask over the instances as they were before filtering, in that order:
Truewhere the instance was kept,Falsewhere it was removed.
Raises:
-
ValueError–If
max_runtimeis not positive.