Python 添加';至少休息一天';约束
下面我简化了一个我正在尝试做的例子。我有一个每周的时间表和几个不同的“时段”要填补,在这里我最大限度地利用分配给每个时段的每个人的给定值 我试图添加一个约束条件,即他们每人都可以休息一天。我见过类似的问题,但我很难把它们翻译成这样,所以任何帮助都是感激的 我的想法是,我可以取每个人每天的最大值,即他们当前分配的任何一天的最大值为1,然后将所有天的最大值相加,并尝试使其小于或等于2(3天中的2天)Python 添加';至少休息一天';约束,python,or-tools,Python,Or Tools,下面我简化了一个我正在尝试做的例子。我有一个每周的时间表和几个不同的“时段”要填补,在这里我最大限度地利用分配给每个时段的每个人的给定值 我试图添加一个约束条件,即他们每人都可以休息一天。我见过类似的问题,但我很难把它们翻译成这样,所以任何帮助都是感激的 我的想法是,我可以取每个人每天的最大值,即他们当前分配的任何一天的最大值为1,然后将所有天的最大值相加,并尝试使其小于或等于2(3天中的2天) 它为所有3天分配最大值。您不能对ortools创建的变量使用Max、min或 要对这些约束进行建模,
它为所有3天分配最大值。您不能对ortools创建的变量使用
Max、min或
要对这些约束进行建模,只需创建中间变量就更容易了
工作日={
(person,day):model.NewBoolVar(f“{person}-{day}”)
为人处事
日复一日
}
对于人物中的人物:
对于以天为单位的天:
以天[日]为单位的小时:
作业[(人、天、小时)]=model.NewBoolVar(
f“{person}-{day}-{hour}”
)
模型.可加性(
作业[(人、日、时)],工作日[人、日]
)
对于人物中的人物:
model.Add(sum(以天为单位的工作日[人,日])您不能对ortools创建的变量使用max、min或和
要对这些约束进行建模,只需创建中间变量就更容易了
工作日={
(person,day):model.NewBoolVar(f“{person}-{day}”)
为人处事
日复一日
}
对于人物中的人物:
对于以天为单位的天:
以天[日]为单位的小时:
作业[(人、天、小时)]=model.NewBoolVar(
f“{person}-{day}-{hour}”
)
模型.可加性(
作业[(人、日、时)],工作日[人、日]
)
对于人物中的人物:
model.Add(sum(工作日[人,天]以天为单位)这是完美的,有助于我做许多其他类似的事情!我没有考虑过使用这样的AddImplication,非常酷。是的,只是不要忘记这只是一个暗示,根据你想做什么,你可能还需要编写model.Add(sum)(作业[(人,天,小时)],以天为单位[day])==0。仅限nForceif(工作日[person,day].Not())
最后一个等式由AddImplication隐含。您需要的是相反的:model.AddBoolOr([assignments[…])。仅限nForceif(工作日)
。这是完美的,并且有助于我做许多其他类似的事情!我没有考虑过使用这样的AddImplication,非常酷。是的,请不要忘记这只是一个暗示,取决于你想做什么,你可能还必须编写模型。添加(天中小时的总和(任务[(人,天,小时)]==0).OnlyEnforceIf(工作日[person,day].Not())
最后一个等式由AddImplication隐含。您需要的是相反的:model.AddBoolOr([assignments[…])。OnlyEnforceIf(工作日)
。
from ortools.sat.python import cp_model
model = cp_model.CpModel()
assignments = {}
people = ['Max','Josh']
days = {
'Monday':['7','8','9','10'],
'Tuesday':['6','7','8','9','10'],
'Wednesday':['7','8','9','10']
}
default_thing_we_like = 50
thing_we_like_per_employee_per_slot = {
('Max','Monday','7'): 100,
('Max','Tuesday','7'): 150,
('Max','Wednesday','7'): 200,
}
# make vars
for person in people:
for day in days:
for hour in days[day]:
assignments[(person,day,hour)] = model.NewBoolVar(f'{person}-{day}-{hour}')
# fill each spot
for day in days:
for hour in days[day]:
model.Add(sum(assignments[(person,day,hour)] for person in people) == 1)
# everyone should get at least one of these days off
for person in people:
for day in days:
model.Add(sum(max(assignments.get((person,day,hour),0) for hour in days[day]) for day in days) <= 2)
solver = cp_model.CpSolver()
model.Maximize(sum(thing_we_like_per_employee_per_slot.get((person, day, hour),default_thing_we_like) * assignments[(person,day,hour)]
for hour in days[day]
for day in days
for person in people
))
solution_printer = cp_model.ObjectiveSolutionPrinter()
status = solver.SolveWithSolutionCallback(model, solution_printer)
if status == cp_model.OPTIMAL or status == cp_model.FEASIBLE:
ret_slots = []
for person in people:
print(f"{person} is working: ")
for day in days:
for hour in days[day]:
if (solver.Value(assignments[(person,day,hour)])):
print(f"{day} at {hour} with",thing_we_like_per_employee_per_slot.get((person, day, hour),default_thing_we_like),"things we like.")
else:
print("uh oh")
Solution 0, time = 0.00 s, objective = 900
Max is working:
Monday at 7 with 100 things we like.
Monday at 9 with 50 things we like.
Tuesday at 6 with 50 things we like.
Tuesday at 7 with 150 things we like.
Tuesday at 8 with 50 things we like.
Tuesday at 9 with 50 things we like.
Tuesday at 10 with 50 things we like.
Wednesday at 7 with 200 things we like.
Wednesday at 8 with 50 things we like.
Wednesday at 9 with 50 things we like.
Wednesday at 10 with 50 things we like.
Josh is working:
Monday at 8 with 50 things we like.
Monday at 10 with 50 things we like.
for person in people:
model.Add(sum(works_day[person, day] for day in days) <= 2)