使用 OR-tools 解决多参与者分配问题
Posted
技术标签:
【中文标题】使用 OR-tools 解决多参与者分配问题【英文标题】:Solving a multi-attendee assignment problem with OR-tools 【发布时间】:2021-05-03 13:26:22 【问题描述】:我正在尝试使用 Python 中的 OR 工具(OR 工具的新手)解决类似于 https://developers.google.com/optimization/assignment/assignment_groups 的分配问题。即,我想将会议分配给 4 个时间段,供 3 位与会者使用。我被告知参加者 1 应该参加 M1、M2、M3,参加者 2 应该参加 M2、M3、M5,参加者 3 应该参加 M3、M4、M5。其他限制是没有时间段有超过一个会议(对于每个与会者),并且每个会议都被分配到一个时间段(对于每个与会者)。为简单起见,我假设每个与会者都有 4 个空闲时间段。
!pip install ortools
from ortools.sat.python import cp_model # CP-SAT solver (primary constraint solver of ORtools)
from ortools.linear_solver import pywraplp
from __future__ import print_function
from ortools.sat.python import cp_model
model = cp_model.CpModel()
num_meetings = 5
num_slots = 4
#attendees X meetings
my_array = [[1,1,0,0,1],[0,1,1,0,1],[0,0,1,1,1]]
#meetings X attendees
my_array_2 = [[0], [0,1], [1,2], [2], [0,1,2]]
# Declare the variables.
a = []
for i in range(3):
b = []
for j in range(num_meetings):
c = []
for k in range(num_slots):
c.append(model.NewIntVar(0, 1, "a[%i,%i,%i]" % (i, j, k)))
b.append(c)
a.append(b)
a_array = [a[i][j][k] for i in range(3) for j in range(num_meetings) for k in range(num_slots)]
#Define the attendees of each meeting:
for d in range(3):
for s in range(num_meetings):
model.Add(sum(a[d][s][k] for k in range(num_slots)) == my_array[d][s])
#Requirement 1: no timeslot has more than one meeting mapped to it,
for d in range(3):
for k in range(num_slots):
model.Add(sum(a[d][s][k] for s in range(num_meetings)) <= 1)
#Requirement 2:
#this should force the attendees with the same meetings to have the same time slot
for i in range(num_meetings):
print('meeting',i+1)
print('------------')
for j in range(len(my_array_2[i])):
print('attendee',my_array_2[i][j]+1)
model.Add(sum(a[my_array_2[i][j]][i][k] for k in range(num_slots)) == 1)
print('------------')
#call the solver:
solver = cp_model.CpSolver()
status = solver.Solve(model)
if status == cp_model.OPTIMAL or status == cp_model.FEASIBLE:
print('Solved')
else:
print(status)
#print the solutions
for i in range(3):
for j in range(num_meetings):
for k in range(num_slots):
if solver.Value(a[i][j][k]) == 1:
print('user',i+1,'meeting',j+1,'slot',k+1, 'value:',solver.Value(a[i][j][k]))
求解器工作到某一点,因为它正确地分配了每个会议,没有与会者在同一时间段内参加多个会议。但是,由于某种原因,该解决方案强制前 3 个时间段中的所有会议,导致最后一个时间段对每个与会者都是空闲的。这会导致与会者参加同一个会议,但每个人都处于不同的时间段。理想情况下,要求 2 将强制同一会议的与会者在同一时间段开会。
【问题讨论】:
你有 5 个会议,只有 4 个空位... 移除一个空位只能举行 如果meet
是一维数组,它只能模拟 1 位与会者
感谢@Stradivari,但是我仍然希望对每个参与者都保持这种约束。 (他们每个人只需要参加 5 次会议中的 3 次,因此是可行的)。我该怎么做?
【参考方案1】:
-
如果问题由于容量问题不可行,则没有额外的约束使其可行
您正在向同一个变量列表中添加 3 个不兼容的 AddAllowedAssignment() 约束。
【讨论】:
感谢您的回复。如果每个与会者都正确映射到他们的 3 个相应会议(我尝试在 AddAllowedAssignment() 中执行此操作),容量问题将得到解决。我怎样才能更好地定义这个问题?以上是关于使用 OR-tools 解决多参与者分配问题的主要内容,如果未能解决你的问题,请参考以下文章
Or-Tools CpSolver 获取最小和最大总和或绝对值
使用 Python 中的 OR-Tools CP Solver(多背包)进行包裹运输(包裹合并)