Skip to content

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 Type Description
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:

Name Type Description Default
ax Axes | None

Matplotlib axes to draw on. Creates a new figure if None.

None

Returns:

Type Description
Axes

The axes with the plot.

to_string() -> str

Print the data.

Returns:

Type Description
str

String representation of the data.

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:

Name Type Description Default
n_nurses int

Number of nurses available for scheduling.

required
n_shifts int

Number of shifts in the schedule.

required
workforce ndarray | list[float]

Required workforce W(d) for each shift d. 1D array of length n_shifts.

required
effort ndarray | list[float]

Effort level E(n) for each nurse n. 1D array of length n_nurses.

required
max_shifts ndarray | list[int]

Maximum number of (weighted) shifts F(n) each nurse can work. 1D array of length n_nurses.

required
shift_weight ndarray | list[float]

Weight for each shift. 1D array of length n_shifts.

required
day_off_priority ndarray | list[list[float]]

Priority matrix g(n,d) for day-off requests. 2D array of shape (n_nurses, n_shifts).

required

Returns:

Type Description
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:

Name Type Description Default
n_nurses int

Number of nurses, by default 10.

10
n_shifts int

Number of shifts, by default 14.

14
shift_system str

Either "two_shift" or "three_shift", by default "two_shift". Controls how shift weights are generated.

'two_shift'
seed int | None

Random seed for reproducibility, by default None.

None

Returns:

Type Description
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 Luna Model'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:

Name Type Description Default
data NurseSchedulingData

The problem data.

required

Returns:

Type Description
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:

Name Type Description Default
data NurseSchedulingData

The Nurse Scheduling instance data.

required

Returns:

Type Description
Model

A Luna Model ready to be solved.

Raises:

Type Description
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:

Name Type Description Default
solution Solution

The solver solution containing variable assignments.

required
data NurseSchedulingData

The original Nurse Scheduling instance data.

required

Returns:

Type Description
NurseSchedulingSolution

A structured solution object with schedule and metrics.

Raises:

Type Description
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 Type Description
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:

Name Type Description Default
data NurseSchedulingData | None

Problem data. When provided, workforce coverage info is shown.

None
ax Axes | None

Matplotlib axes to draw on. Creates a new figure if None.

None

Returns:

Type Description
Axes

The axes with the plot.

to_string() -> str

Print the solution.

Returns:

Type Description
str

String representation of the solution.

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, max_num_nurses: int, num_instances: int = 1, *, 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:

Name Type Description Default
min_num_nurses int

Minimum number of nurses per instance.

required
max_num_nurses int

Maximum number of nurses per instance.

required
num_instances int

Number of instances per size, by default 1.

1
n_shifts int

Number of shifts per instance, by default 14.

14
shift_system str

Either "two_shift" or "three_shift", by default "two_shift".

'two_shift'
seed int | None

Random seed for reproducibility, by default None.

None

Returns:

Type Description
NurseSchedulingCollection

Collection containing generated instances.

Examples:

>>> collection = NurseSchedulingCollection.from_random(
...     min_num_nurses=5,
...     max_num_nurses=10,
...     num_instances=2,
...     seed=42,
... )

from_two_shift(min_num_nurses: int, max_num_nurses: int, num_instances: int = 1, *, 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:

Name Type Description Default
min_num_nurses int

Minimum number of nurses per instance.

required
max_num_nurses int

Maximum number of nurses per instance.

required
num_instances int

Number of instances per size, by default 1.

1
n_shifts int

Number of shifts per instance, by default 14.

14
seed int | None

Random seed for reproducibility, by default None.

None

Returns:

Type Description
NurseSchedulingCollection

Collection containing 2-shift system instances.

Examples:

>>> collection = NurseSchedulingCollection.from_two_shift(
...     min_num_nurses=5,
...     max_num_nurses=10,
...     seed=42,
... )

from_three_shift(min_num_nurses: int, max_num_nurses: int, num_instances: int = 1, *, 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:

Name Type Description Default
min_num_nurses int

Minimum number of nurses per instance.

required
max_num_nurses int

Maximum number of nurses per instance.

required
num_instances int

Number of instances per size, by default 1.

1
n_shifts int

Number of shifts per instance, by default 21 (7 days * 3 shifts).

21
seed int | None

Random seed for reproducibility, by default None.

None

Returns:

Type Description
NurseSchedulingCollection

Collection containing 3-shift system instances.

Examples:

>>> collection = NurseSchedulingCollection.from_three_shift(
...     min_num_nurses=8,
...     max_num_nurses=15,
...     seed=42,
... )