Медсестра Расписание

Рассмотрим задачу планирования работы медсестры в отделении конкретной больницы. Ежедневно работают три смены по 12 часов, начиная с 7, 13 и 19 часов. Горизонт планирования составляет четыре дня, начиная с 01 мая 2023 г., всего 12 смен. В эти смены могут быть назначены четыре дипломированные медсестры, с целью иметь в отделении две медсестры в любой момент времени. Требование о покрытии является обязательным.

Всем медсестрам необходимо отдыхать между сменами не менее 12 часов (720 минут) и они могут работать не более 36 часов (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
      }
    },
    ...
    ]
  }

Пример с 12 сменами (четыре дня по три смены в день)


    {
      "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
      }
    }]
  }
  

Отдых между сменами

Чтобы представить отдых между сменами для сотрудника, используйте поле minimumRestMinutes из ограничения планирования . Время начала и окончания ограничения используется для определения того, какие смены следует учитывать, и поэтому должно соответствовать горизонту планирования, перекрываясь со всеми сменами. Время отдыха указывается в минутах (720), а приоритет PRIORITY_HIGH , как указано выше. Первая медсестра (по имени Адам) представлена ​​как:

  {
    "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
      }]
    }
  }

Максимальное время работы

Максимальное количество времени, в течение которого сотрудник может работать, также представлено ограничением планирования с использованием поля maximumMinutes . Максимальное время работы в этом примере составляет 2160 минут. Время начала и окончания ограничения должно соответствовать всему горизонту планирования. Соответствующее представление первой медсестры (Адама) можно обновить до:

  {
    "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
      }]
    }
  }

Пример со всеми четырьмя сотрудниками


  {
      "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
        }]
      }]
  }
  

Страхование дипломированных медсестер

Охват двух дипломированных медсестер в любой момент времени представлен требованием о покрытии . В частности, roleRequirements заполняется одним требованием роли , для которого roleId имеет значение «Registered Nurse», targetEmployeeCount имеет значение 2, а priority установлен на PRIORITY_MANDATORY . Время начала и окончания действия страхового покрытия должно совпадать в каждую смену. В поле locationId установлено значение «department», поэтому учитываются только смены, происходящие в этом месте.

  {
    "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"]
  }

Пример полного запроса


    {
      "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"]
    }
    

Пример ответа

Ответ решателя содержит распределение медсестер по сменам и статус процедуры оптимизации. Например, смены, назначенные первому сотруднику, возвращаются как:

  {
    "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"
      },
      ... ]
  }

Пример полного ответа


    {
      "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"
        }
      ]
    }