使用 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 解决多参与者分配问题的主要内容,如果未能解决你的问题,请参考以下文章

ORTools 任务分配优化与持续时间

Or-Tools CpSolver 获取最小和最大总和或绝对值

公平班次分配

使用 Python 中的 OR-Tools CP Solver(多背包)进行包裹运输(包裹合并)

学界 | 代替支持向量机,南大周志华组提出多类最优边界分配机mcODM

Yottachain专业矿机分配百万美金存储市场你参与了吗?