Установите требование о максимальном количестве часов в день в задаче PuLP

Я пытаюсь настроить свою проблему PuLP, чтобы у сотрудника не было более 10 часов в день.

Я настроил следующую переменную сотрудника:

cost = []
vars_by_shift = defaultdict(list)

for employee, info in employees.iterrows():
    for shift in info['availability']:
        employee_var = pl.LpVariable("%s_%s" % (employee, shift), 0, 1, pl.LpInteger)
        vars_by_shift[shift].append(employee_var)
        cost.append(employee_var * info['base_rate'])

Моя цель - минимизировать затраты:

prob = pl.LpProblem("scheduling", pl.LpMinimize)
prob += sum(cost)

Пример моих данных смены:

"76749": {
    "start_date": "2019-08-14",
    "start_time": "08:00",
    "end_date": "2019-08-14",
    "end_time": "12:00",
    "duration": 4,
    "number_positions": 1
},
"76750": {
    "start_date": "2019-08-14",
    "start_time": "13:00",
    "end_date": "2019-08-14",
    "end_time": "20:00",
    "duration": 7,
    "number_positions": 1
}

Иногда сотруднику может быть назначено две короткие смены в один и тот же день. Я хочу, чтобы общее количество часов в реестре сотрудников в любой день не превышало 10 часов. Как смоделировать это ограничение?


person Adam    schedule 20.08.2019    source источник
comment
Есть разные способы смоделировать это в зависимости от ситуации. Иногда мы можем перечислить все возможные комбинации смен, которые может работать сотрудник, а затем выбрать в модели не более одной комбинации смен. Вы также можете просто использовать все смены и просто запретить комбинации смен, которые не разрешены. Вы также можете смоделировать комбинацию сдвигов внутри модели оптимизации, но для этого часто требуются нетривиальные ограничения. Наконец, для этого типа моделей часто используется генерация столбцов. Это снова требует тщательного моделирования того, что разрешено как комбинация смен.   -  person Erwin Kalvelagen    schedule 20.08.2019


Ответы (2)


Если я понимаю вашу реализацию, у вас есть набор двоичных переменных решения:

pl[e, s]

С одной переменной для каждого e в employees и для каждого s в shifts

Я также предполагаю, что существует (или вы можете легко создать) список days, который включает список дней, охваченных сменами, и вы можете легко написать функцию, которая возвращает количество часов смены в конкретный день.

Затем вы хотите добавить ограничения:

for e in employees:
    for d in days:
        lpSum([pl[e, s]*n_hours_of_shift_in_day(s, d) for s in shifts]) <= 10.0

Где функция n_hours_of_shift_in_day(s, d) - это функция, которая возвращает количество часов смены s в день d, например, если ваша смена была:

"76749": {
    "start_date": "2019-08-14",
    "start_time": "18:00",
    "end_date": "2019-08-15",
    "end_time": "19:00",
    "duration": 25,
    "number_positions": 1
}

Тогда n_hours_of_shift_in_day("76749", "2019-08-14") вернет 5.0, а n_hours_of_shift_in_day("76749", "2019-08-15") вернет 19.0.

Также в вашем примере смены, похоже, используется 12-часовой формат времени без указания AM или PM, что может вызвать некоторые проблемы.

person kabdulla    schedule 20.08.2019
comment
Мне нужно просуммировать все смены, назначенные сотруднику на день, например 2019-08-14 и убедитесь, что общее количество часов меньше максимального. Я обновил вам пример смены. Какие-либо предложения. - person Adam; 22.08.2019
comment
Набор ограничений, которые я перечислил выше, выполняет то, что вы просите для каждого сотрудника и для каждого дня. Это требует, чтобы вы написали функцию n_hours_of_shift_in_day. Если ваши смены никогда не переходят от одного дня к другому, это должно быть очень просто. - person kabdulla; 22.08.2019

ну, вам нужна группирующая переменная для часов, считается ли она start_date днем, когда вы не хотите назначать более 10 часов?

если ответ положительный

тогда тебе нужно что-то вроде этого ....

emp in employees.iterrows():
    for d in dates:
        prob.addConstrain(pl.lpSum([ employee_var*vars_by_shift[s][hours] if vars_by_shift[s]==d else 0 for s in shifts]) < 10)
person Daniel Fischer    schedule 20.08.2019
comment
но vars_by_shift не имеет [hours] переменной ...? - person Adam; 20.08.2019