Files
OperatorSchedule/main.py
2026-04-04 16:41:25 +05:00

101 lines
3.7 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
from ortools.sat.python import cp_model
import csv
# Определяем даты апреля 2026 года
days = [
"2026-04-{:02d}".format(i) for i in range(1, 31)
]
# Смены
shifts = [
(6, 14.5), # с 06:00 до 14:30
(8, 16.5), # с 08:00 до 16:30
(11.5, 20), # с 11:30 до 20:00
(12.5, 21) # с 12:30 до 21:00
]
# Операторы и их пожелания
operators = [
"Иванов",
"Алексеев",
"Сидоров",
"Козобородов",
"Трудяшкина",
"Петрова"
]
operator_preferences = {
"Иванов": ["2026-04-10", "2026-04-13"],
"Алексеев": [(i, 0) for i in days if (int(i[-2:]) - 1) % 7 == 0], # Понедельники
"Сидоров": ["2026-04-25", "2026-04-26"],
"Козобородов": [(i, 2) for i in days], # Предпочитает смену 11:3020:00
"Трудяшкина": ["2026-04-04"],
"Петрова": ["2026-04-08", "2026-04-29"]
}
# Создаем модель
model = cp_model.CpModel()
# Переменные: определяем, работает ли оператор на смене в день
works = {}
for day in days:
for shift_idx in range(len(shifts)):
for op in operators:
works[(day, shift_idx, op)] = model.NewBoolVar(f"{op}_{day}_shift_{shift_idx}")
# # Пожелания операторов
for op, prefs in operator_preferences.items():
if isinstance(prefs, list):
for pref in prefs:
if isinstance(pref, tuple):
day, shift = pref
model.AddHint(works[day, shift, op], 1)
else:
day = pref
model.Add(sum(works[day, shift_idx, op] for shift_idx in range(len(shifts))) == 0)
# Условие 1: На каждую смену должен быть назначен оператор
for day in days:
for shift_idx in range(len(shifts)):
model.Add(sum(works[day, shift_idx, op] for op in operators) == 1)
# Условие 2: У каждого оператора должно быть 8 выходных
for op in operators:
model.Add(sum(works[day, shift_idx, op] for day in days for shift_idx in range(len(shifts))) == 20 )
# Условие 3: Оператор не должен работать больше 5 дней подряд
for op in operators:
for day_idx in range(len(days) - 4):
model.Add(sum(works[days[day_idx + i], shift_idx, op] for i in range(5) for shift_idx in range(len(shifts))) <= 4)
# Условие 4: В день оператор может работать только одну смену
for day in days:
for op in operators:
model.Add(sum(works[day, shift_idx, op] for shift_idx in range(len(shifts))) <= 1)
# Решаем модель
solver = cp_model.CpSolver()
status = solver.Solve(model)
if status != cp_model.OPTIMAL and status != cp_model.FEASIBLE:
print("Невозможно составить график")
else:
# Создаем CSV файл с результатами
with open('shift_schedule.csv', 'w', newline='', encoding='utf-8') as file:
writer = csv.writer(file)
writer.writerow(['Day'] + [f'{i+1} shift' for i in range(len(shifts))])
for day in days:
row = [day]
for shift_idx in range(len(shifts)):
op = None
for op_name in operators:
if solver.Value(works[day, shift_idx, op_name]) == 1:
op = op_name
break
row.append(op)
writer.writerow(row)
print("График успешно составлен и сохранен в 'shift_schedule.csv'")