Programación de enfermeros

Considera la posibilidad de que un enfermero tenga un problema de programación para un departamento de un hospital determinado. Todos los días, hay tres turnos de 12 horas que comienzan en 7h, 13h, 19h. El el horizonte de planificación es de cuatro días, a partir del 1 de mayo de 2023, para un total de 12 turnos. Hay cuatro enfermeras registradas que pueden asignarse a estos turnos, con la objetivo de tener dos enfermeras en el departamento en cualquier momento. La cobertura este requisito es obligatorio.

Todas las enfermeras deben descansar entre turnos durante al menos 12 horas (720 minutos). pueden funcionar como máximo 36 horas (2,160 minutos) durante el horizonte de planificación especificado. Estas restricciones tienen prioridad alta y media, respectivamente.

Varios cambios por día

Tres turnos por día se representan como tres turnos independientes. Por ejemplo: turnos el primer día (en cada cuatro días) en el "departamento" ubicación son se representa de la siguiente manera:

  {
    "shifts": [{
      "id": "2023-05-01 7hr",
      "locationId": "department",
      "startDateTime": {
        "year": 2023,
        "month": 5,
        "day": 1,
        "hours": 7
      },
      "endDateTime": {
        "year": 2023,
        "month": 5,
        "day": 1,
        "hours": 19
      }
    }, {
      "id": "2023-05-01 13hr",
      "locationId": "department",
      "startDateTime": {
        "year": 2023,
        "month": 5,
        "day": 1,
        "hours": 13
      },
      "endDateTime": {
        "year": 2023,
        "month": 5,
        "day": 2,
        "hours": 1
      }
    }, {
      "id": "2023-05-01 19hr",
      "locationId": "department",
      "startDateTime": {
        "year": 2023,
        "month": 5,
        "day": 1,
        "hours": 19
      },
      "endDateTime": {
        "year": 2023,
        "month": 5,
        "day": 2,
        "hours": 7
      }
    },
    ...
    ]
  }

Ejemplo con 12 turnos (cuatro días con tres turnos por día)


    {
      "shifts": [{
      "id": "2023-05-01 7hr",
      "locationId": "department",
      "startDateTime": {
        "year": 2023,
        "month": 5,
        "day": 1,
        "hours": 7
      },
      "endDateTime": {
        "year": 2023,
        "month": 5,
        "day": 1,
        "hours": 19
      }
    }, {
      "id": "2023-05-01 13hr",
      "locationId": "department",
      "startDateTime": {
        "year": 2023,
        "month": 5,
        "day": 1,
        "hours": 13
      },
      "endDateTime": {
        "year": 2023,
        "month": 5,
        "day": 2,
        "hours": 1
      }
    }, {
      "id": "2023-05-01 19hr",
      "locationId": "department",
      "startDateTime": {
        "year": 2023,
        "month": 5,
        "day": 1,
        "hours": 19
      },
      "endDateTime": {
        "year": 2023,
        "month": 5,
        "day": 2,
        "hours": 7
      }
    }, {
      "id": "2023-05-02 7hr",
      "locationId": "department",
      "startDateTime": {
        "year": 2023,
        "month": 5,
        "day": 2,
        "hours": 7
      },
      "endDateTime": {
        "year": 2023,
        "month": 5,
        "day": 2,
        "hours": 19
      }
    }, {
      "id": "2023-05-02 13hr",
      "locationId": "department",
      "startDateTime": {
        "year": 2023,
        "month": 5,
        "day": 2,
        "hours": 13
      },
      "endDateTime": {
        "year": 2023,
        "month": 5,
        "day": 3,
        "hours": 1
      }
    }, {
      "id": "2023-05-02 19hr",
      "locationId": "department",
      "startDateTime": {
        "year": 2023,
        "month": 5,
        "day": 2,
        "hours": 19
      },
      "endDateTime": {
        "year": 2023,
        "month": 5,
        "day": 3,
        "hours": 7
      }
    }, {
      "id": "2023-05-03 7hr",
      "locationId": "department",
      "startDateTime": {
        "year": 2023,
        "month": 5,
        "day": 3,
        "hours": 7
      },
      "endDateTime": {
        "year": 2023,
        "month": 5,
        "day": 3,
        "hours": 19
      }
    }, {
      "id": "2023-05-03 13hr",
      "locationId": "department",
      "startDateTime": {
        "year": 2023,
        "month": 5,
        "day": 3,
        "hours": 13
      },
      "endDateTime": {
        "year": 2023,
        "month": 5,
        "day": 4,
        "hours": 1
      }
    }, {
      "id": "2023-05-03 19hr",
      "locationId": "department",
      "startDateTime": {
        "year": 2023,
        "month": 5,
        "day": 3,
        "hours": 19
      },
      "endDateTime": {
        "year": 2023,
        "month": 5,
        "day": 4,
        "hours": 7
      }
    }, {
      "id": "2023-05-04 7hr",
      "locationId": "department",
      "startDateTime": {
        "year": 2023,
        "month": 5,
        "day": 4,
        "hours": 7
      },
      "endDateTime": {
        "year": 2023,
        "month": 5,
        "day": 4,
        "hours": 19
      }
    }, {
      "id": "2023-05-04 13hr",
      "locationId": "department",
      "startDateTime": {
        "year": 2023,
        "month": 5,
        "day": 4,
        "hours": 13
      },
      "endDateTime": {
        "year": 2023,
        "month": 5,
        "day": 5,
        "hours": 1
      }
    }, {
      "id": "2023-05-04 19hr",
      "locationId": "department",
      "startDateTime": {
        "year": 2023,
        "month": 5,
        "day": 4,
        "hours": 19
      },
      "endDateTime": {
        "year": 2023,
        "month": 5,
        "day": 5,
        "hours": 7
      }
    }]
  }
  

Descanso entre turnos

Para representar el resto entre los turnos de un empleado, usa la minimumRestMinutes de un restricción de programación. Las horas de inicio y finalización de la restricción se usan para determinar qué cambios considerar y, por lo tanto, deben alinearse con un horizonte de planificación superponiendose con todos los cambios. El el tiempo de descanso se especifica en minutos (720) y la prioridad es PRIORITY_HIGH como que se mencionaron anteriormente. La primera enfermera (llamada Adam) se representa de la siguiente manera:

  {
    "employees": [{
      "id": "Adam",
      "roleIds": ["Registered Nurse"],
      "schedulingConstraints": [{
        "priority": "PRIORITY_HIGH",
        "startDateTime": {
          "year": 2023,
          "month": 5,
          "day": 1,
          "hours": 7
        },
        "endDateTime": {
          "year": 2023,
          "month": 5,
          "day": 5,
          "hours": 7
        },
        "minimumRestMinutes": 720
      }]
    }
  }

Tiempo máximo de trabajo

La cantidad máxima de tiempo que un empleado puede trabajar también se representa con una restricción de programación con maximumMinutes . El tiempo de trabajo máximo en este ejemplo es de 2,160 minutos. El inicio y las horas de finalización de la restricción deben alinearse con todo el horizonte de planificación. El la representación correspondiente del primer enfermero (Adam) se puede actualizar a:

  {
    "employees": [{
      "id": "Adam",
      "roleIds": ["Registered Nurse"],
      "schedulingConstraints": [{
        "priority": "PRIORITY_HIGH",
        "startDateTime": {
          "year": 2023,
          "month": 5,
          "day": 1,
          "hours": 7
        },
        "endDateTime": {
          "year": 2023,
          "month": 5,
          "day": 5,
          "hours": 7
        },
        "minimumRestMinutes": 720
      }, {
        "priority": "PRIORITY_MEDIUM",
        "startDateTime": {
          "year": 2023,
          "month": 5,
          "day": 1,
          "hours": 7
        },
        "endDateTime": {
          "year": 2023,
          "month": 5,
          "day": 5,
          "hours": 7
        },
        "maximumMinutes": 2160
      }]
    }
  }

Ejemplo con los cuatro empleados


  {
      "employees": [{
        "id": "Adam",
        "roleIds": ["Registered Nurse"],
        "schedulingConstraints": [{
          "priority": "PRIORITY_HIGH",
          "startDateTime": {
            "year": 2023,
            "month": 5,
            "day": 1,
            "hours": 7
          },
          "endDateTime": {
            "year": 2023,
            "month": 5,
            "day": 5,
            "hours": 7
          },
          "minimumRestMinutes": 720
        }, {
          "priority": "PRIORITY_MEDIUM",
          "startDateTime": {
            "year": 2023,
            "month": 5,
            "day": 1,
            "hours": 7
          },
          "endDateTime": {
            "year": 2023,
            "month": 5,
            "day": 5,
            "hours": 7
          },
          "maximumMinutes": 2160
        }]
      }, {
        "id": "Grace",
        "roleIds": ["Registered Nurse"],
        "schedulingConstraints": [{
          "priority": "PRIORITY_HIGH",
          "startDateTime": {
            "year": 2023,
            "month": 5,
            "day": 1,
            "hours": 7
          },
          "endDateTime": {
            "year": 2023,
            "month": 5,
            "day": 5,
            "hours": 7
          },
          "minimumRestMinutes": 720
        }, {
          "priority": "PRIORITY_MEDIUM",
          "startDateTime": {
            "year": 2023,
            "month": 5,
            "day": 1,
            "hours": 7
          },
          "endDateTime": {
            "year": 2023,
            "month": 5,
            "day": 5,
            "hours": 7
          },
          "maximumMinutes": 2160
        }]
      }, {
        "id": "James",
        "roleIds": ["Registered Nurse"],
        "schedulingConstraints": [{
          "priority": "PRIORITY_HIGH",
          "startDateTime": {
            "year": 2023,
            "month": 5,
            "day": 1,
            "hours": 7
          },
          "endDateTime": {
            "year": 2023,
            "month": 5,
            "day": 5,
            "hours": 7
          },
          "minimumRestMinutes": 720
        }, {
          "priority": "PRIORITY_MEDIUM",
          "startDateTime": {
            "year": 2023,
            "month": 5,
            "day": 1,
            "hours": 7
          },
          "endDateTime": {
            "year": 2023,
            "month": 5,
            "day": 5,
            "hours": 7
          },
          "maximumMinutes": 2160
        }]
      }, {
        "id": "Alonso",
        "roleIds": ["Registered Nurse"],
        "schedulingConstraints": [{
          "priority": "PRIORITY_HIGH",
          "startDateTime": {
            "year": 2023,
            "month": 5,
            "day": 1,
            "hours": 7
          },
          "endDateTime": {
            "year": 2023,
            "month": 5,
            "day": 5,
            "hours": 7
          },
          "minimumRestMinutes": 720
        }, {
          "priority": "PRIORITY_MEDIUM",
          "startDateTime": {
            "year": 2023,
            "month": 5,
            "day": 1,
            "hours": 7
          },
          "endDateTime": {
            "year": 2023,
            "month": 5,
            "day": 5,
            "hours": 7
          },
          "maximumMinutes": 2160
        }]
      }]
  }
  

Cobertura para enfermeros matriculados

La cobertura de dos enfermeros matriculados en un momento dado se representa con una requisito de cobertura. En particular, roleRequirements se completa con una requisito del rol para el que roleId está configurado como "Enfermero registrado", targetEmployeeCount está establecido en 2 y priority en PRIORITY_MANDATORY Las horas de inicio y finalización del requisito de cobertura se superponen con cada turno. El campo locationId está configurado como "department" para que solo se consideran los cambios que ocurren en esta ubicación.

  {
    "coverageRequirements": [{
      "startDateTime": {
        "year": 2023,
        "month": 5,
        "day": 1,
        "hours": 7
      },
      "endDateTime": {
        "year": 2023,
        "month": 5,
        "day": 5,
        "hours": 7
      },
      "locationId": "department",
      "roleRequirements": [{
        "roleId": "Registered Nurse",
        "targetEmployeeCount": 2,
        "priority": "PRIORITY_MANDATORY"
      }]
    }],
    "roleIds": ["Registered Nurse"],
    "locationIds": ["department"]
  }

Ejemplo de una solicitud completa


    {
      "employees": [{
        "id": "Adam",
        "roleIds": ["Registered Nurse"],
        "schedulingConstraints": [{
          "priority": "PRIORITY_HIGH",
          "startDateTime": {
            "year": 2023,
            "month": 5,
            "day": 1,
            "hours": 7
          },
          "endDateTime": {
            "year": 2023,
            "month": 5,
            "day": 5,
            "hours": 7
          },
          "minimumRestMinutes": 720
        }, {
          "priority": "PRIORITY_MEDIUM",
          "startDateTime": {
            "year": 2023,
            "month": 5,
            "day": 1,
            "hours": 7
          },
          "endDateTime": {
            "year": 2023,
            "month": 5,
            "day": 5,
            "hours": 7
          },
          "maximumMinutes": 2160
        }]
      }, {
        "id": "Grace",
        "roleIds": ["Registered Nurse"],
        "schedulingConstraints": [{
          "priority": "PRIORITY_HIGH",
          "startDateTime": {
            "year": 2023,
            "month": 5,
            "day": 1,
            "hours": 7
          },
          "endDateTime": {
            "year": 2023,
            "month": 5,
            "day": 5,
            "hours": 7
          },
          "minimumRestMinutes": 720
        }, {
          "priority": "PRIORITY_MEDIUM",
          "startDateTime": {
            "year": 2023,
            "month": 5,
            "day": 1,
            "hours": 7
          },
          "endDateTime": {
            "year": 2023,
            "month": 5,
            "day": 5,
            "hours": 7
          },
          "maximumMinutes": 2160
        }]
      }, {
        "id": "James",
        "roleIds": ["Registered Nurse"],
        "schedulingConstraints": [{
          "priority": "PRIORITY_HIGH",
          "startDateTime": {
            "year": 2023,
            "month": 5,
            "day": 1,
            "hours": 7
          },
          "endDateTime": {
            "year": 2023,
            "month": 5,
            "day": 5,
            "hours": 7
          },
          "minimumRestMinutes": 720
        }, {
          "priority": "PRIORITY_MEDIUM",
          "startDateTime": {
            "year": 2023,
            "month": 5,
            "day": 1,
            "hours": 7
          },
          "endDateTime": {
            "year": 2023,
            "month": 5,
            "day": 5,
            "hours": 7
          },
          "maximumMinutes": 2160
        }]
      }, {
        "id": "Alonso",
        "roleIds": ["Registered Nurse"],
        "schedulingConstraints": [{
          "priority": "PRIORITY_HIGH",
          "startDateTime": {
            "year": 2023,
            "month": 5,
            "day": 1,
            "hours": 7
          },
          "endDateTime": {
            "year": 2023,
            "month": 5,
            "day": 5,
            "hours": 7
          },
          "minimumRestMinutes": 720
        }, {
          "priority": "PRIORITY_MEDIUM",
          "startDateTime": {
            "year": 2023,
            "month": 5,
            "day": 1,
            "hours": 7
          },
          "endDateTime": {
            "year": 2023,
            "month": 5,
            "day": 5,
            "hours": 7
          },
          "maximumMinutes": 2160
        }]
      }],
      "shifts": [{
        "id": "2023-05-01 7hr",
        "locationId": "department",
        "startDateTime": {
          "year": 2023,
          "month": 5,
          "day": 1,
          "hours": 7
        },
        "endDateTime": {
          "year": 2023,
          "month": 5,
          "day": 1,
          "hours": 19
        }
      }, {
        "id": "2023-05-01 13hr",
        "locationId": "department",
        "startDateTime": {
          "year": 2023,
          "month": 5,
          "day": 1,
          "hours": 13
        },
        "endDateTime": {
          "year": 2023,
          "month": 5,
          "day": 2,
          "hours": 1
        }
      }, {
        "id": "2023-05-01 19hr",
        "locationId": "department",
        "startDateTime": {
          "year": 2023,
          "month": 5,
          "day": 1,
          "hours": 19
        },
        "endDateTime": {
          "year": 2023,
          "month": 5,
          "day": 2,
          "hours": 7
        }
      }, {
        "id": "2023-05-02 7hr",
        "locationId": "department",
        "startDateTime": {
          "year": 2023,
          "month": 5,
          "day": 2,
          "hours": 7
        },
        "endDateTime": {
          "year": 2023,
          "month": 5,
          "day": 2,
          "hours": 19
        }
      }, {
        "id": "2023-05-02 13hr",
        "locationId": "department",
        "startDateTime": {
          "year": 2023,
          "month": 5,
          "day": 2,
          "hours": 13
        },
        "endDateTime": {
          "year": 2023,
          "month": 5,
          "day": 3,
          "hours": 1
        }
      }, {
        "id": "2023-05-02 19hr",
        "locationId": "department",
        "startDateTime": {
          "year": 2023,
          "month": 5,
          "day": 2,
          "hours": 19
        },
        "endDateTime": {
          "year": 2023,
          "month": 5,
          "day": 3,
          "hours": 7
        }
      }, {
        "id": "2023-05-03 7hr",
        "locationId": "department",
        "startDateTime": {
          "year": 2023,
          "month": 5,
          "day": 3,
          "hours": 7
        },
        "endDateTime": {
          "year": 2023,
          "month": 5,
          "day": 3,
          "hours": 19
        }
      }, {
        "id": "2023-05-03 13hr",
        "locationId": "department",
        "startDateTime": {
          "year": 2023,
          "month": 5,
          "day": 3,
          "hours": 13
        },
        "endDateTime": {
          "year": 2023,
          "month": 5,
          "day": 4,
          "hours": 1
        }
      }, {
        "id": "2023-05-03 19hr",
        "locationId": "department",
        "startDateTime": {
          "year": 2023,
          "month": 5,
          "day": 3,
          "hours": 19
        },
        "endDateTime": {
          "year": 2023,
          "month": 5,
          "day": 4,
          "hours": 7
        }
      }, {
        "id": "2023-05-04 7hr",
        "locationId": "department",
        "startDateTime": {
          "year": 2023,
          "month": 5,
          "day": 4,
          "hours": 7
        },
        "endDateTime": {
          "year": 2023,
          "month": 5,
          "day": 4,
          "hours": 19
        }
      }, {
        "id": "2023-05-04 13hr",
        "locationId": "department",
        "startDateTime": {
          "year": 2023,
          "month": 5,
          "day": 4,
          "hours": 13
        },
        "endDateTime": {
          "year": 2023,
          "month": 5,
          "day": 5,
          "hours": 1
        }
      }, {
        "id": "2023-05-04 19hr",
        "locationId": "department",
        "startDateTime": {
          "year": 2023,
          "month": 5,
          "day": 4,
          "hours": 19
        },
        "endDateTime": {
          "year": 2023,
          "month": 5,
          "day": 5,
          "hours": 7
        }
      }],
      "coverageRequirements": [{
        "startDateTime": {
          "year": 2023,
          "month": 5,
          "day": 1,
          "hours": 7
        },
        "endDateTime": {
          "year": 2023,
          "month": 5,
          "day": 5,
          "hours": 7
        },
        "locationId": "department",
        "roleRequirements": [{
          "roleId": "Registered Nurse",
          "targetEmployeeCount": 2,
          "priority": "PRIORITY_MANDATORY"
        }]
      }],
      "roleIds": ["Registered Nurse"],
      "locationIds": ["department"]
    }
    

Ejemplo de respuesta

La respuesta de la resolución contiene la asignación de enfermeras a turnos y la estado del procedimiento de optimización. Por ejemplo, los cambios asignados a la primer empleado se devuelven como:

  {
    "solutionStatus": "OPTIMAL",
    "shiftAssignments": [
      {
        "employeeId": "Adam",
        "shiftId": "2023-05-01 7hr",
        "roleId": "Registered Nurse"
      },
      {
        "employeeId": "Adam",
        "shiftId": "2023-05-02 7hr",
        "roleId": "Registered Nurse"
      },
      {
        "employeeId": "Adam",
        "shiftId": "2023-05-03 7hr",
        "roleId": "Registered Nurse"
      },
      {
        "employeeId": "Adam",
        "shiftId": "2023-05-04 7hr",
        "roleId": "Registered Nurse"
      },
      ... ]
  }

Ejemplo de una respuesta completa


    {
      "solutionStatus": "OPTIMAL",
      "shiftAssignments": [
        {
          "employeeId": "Adam",
          "shiftId": "2023-05-01 7hr",
          "roleId": "Registered Nurse"
        },
        {
          "employeeId": "Adam",
          "shiftId": "2023-05-02 7hr",
          "roleId": "Registered Nurse"
        },
        {
          "employeeId": "Adam",
          "shiftId": "2023-05-03 7hr",
          "roleId": "Registered Nurse"
        },
        {
          "employeeId": "Adam",
          "shiftId": "2023-05-04 7hr",
          "roleId": "Registered Nurse"
        },
        {
          "employeeId": "Grace",
          "shiftId": "2023-05-01 19hr",
          "roleId": "Registered Nurse"
        },
        {
          "employeeId": "Grace",
          "shiftId": "2023-05-02 19hr",
          "roleId": "Registered Nurse"
        },
        {
          "employeeId": "Grace",
          "shiftId": "2023-05-03 19hr",
          "roleId": "Registered Nurse"
        },
        {
          "employeeId": "Grace",
          "shiftId": "2023-05-04 19hr",
          "roleId": "Registered Nurse"
        },
        {
          "employeeId": "James",
          "shiftId": "2023-05-01 19hr",
          "roleId": "Registered Nurse"
        },
        {
          "employeeId": "James",
          "shiftId": "2023-05-02 19hr",
          "roleId": "Registered Nurse"
        },
        {
          "employeeId": "James",
          "shiftId": "2023-05-03 19hr",
          "roleId": "Registered Nurse"
        },
        {
          "employeeId": "James",
          "shiftId": "2023-05-04 19hr",
          "roleId": "Registered Nurse"
        },
        {
          "employeeId": "Alonso",
          "shiftId": "2023-05-01 7hr",
          "roleId": "Registered Nurse"
        },
        {
          "employeeId": "Alonso",
          "shiftId": "2023-05-02 7hr",
          "roleId": "Registered Nurse"
        },
        {
          "employeeId": "Alonso",
          "shiftId": "2023-05-03 7hr",
          "roleId": "Registered Nurse"
        },
        {
          "employeeId": "Alonso",
          "shiftId": "2023-05-04 7hr",
          "roleId": "Registered Nurse"
        }
      ]
    }