基于参与者所述兴趣水平的最佳会议角色分配算法

时间:2016-07-04 20:17:13

标签: algorithm optimization linear-programming branch-and-bound tabu-search

我试图找出最好的技术或资源来帮助我解决优化问题。问题是使会议参与者与预定义角色进行最佳匹配。在会议之前,与会者决定每个角色是否为他人:

  • 如果可能的话,积极寻求填补这个角色(" A")
  • 愿意担任这个角色,但对此并不感到强烈(" W")
  • 不愿意担任这个角色(" U")。

例如,可能的输入矩阵是:

目标是在以下限制条件下,为具有标记为" A"的角色的与会者的匹配数量最大化:

  • 所有角色仅由一位与会者填写
  • 与会者标记为" U"是禁止的

对于此示例,最佳解决方案如下,其中使用" A"填充4/5角色。匹配。

有没有人知道是否有更好的方法来解决这种比蛮力更好的问题(对于较大的矩阵来说很快就会变得不可行)?我对自己实现的优化算法(即禁忌搜索,遗传算法,分支定界等)的一般建议持开放态度,甚至可以指向现有包中的功能指针,例如{{ 3}}

谢谢!

2 个答案:

答案 0 :(得分:1)

方法

这是一个简单的整数编程方法,在python中用cvxpy实现。

代码

import numpy as np
from cvxpy import *

""" INPUT """
N_ATTENDEES = 6
N_ROLES = 5
ATTENDEE_CAN_TAKE_MULTIPLE_ROLES = False  # Modelling-decision

A_ROLES = np.array([[1,1,0,0,0],
                    [0,0,0,0,1],
                    [0,1,0,0,0],
                    [1,1,0,0,0],
                    [1,0,0,0,0],
                    [0,1,1,1,0]], dtype=bool)

W_ROLES = np.array([[0,0,0,1,0],
                    [0,0,1,1,0],
                    [1,0,0,1,1],
                    [0,0,0,0,0],
                    [0,0,1,0,1],
                    [0,0,0,0,1]], dtype=bool)

U_ROLES = np.ones((N_ATTENDEES, N_ROLES), dtype=bool) - A_ROLES - W_ROLES

""" Variables """
X = Bool(N_ATTENDEES, N_ROLES)  # 1 -> attendee takes role

""" Constraints """
constraints = []

# (1) All roles assigned to exactly one attendee
for r in range(N_ROLES):
    constraints.append(sum_entries(X[:, r]) == 1)

# (2) Forbidden roles
constraints.append(X <= (1-U_ROLES))

# (3) optional: max one role per attendee
if not ATTENDEE_CAN_TAKE_MULTIPLE_ROLES:
    for a in range(N_ATTENDEES):
        constraints.append(sum_entries(X[a, :]) <= 1)

""" Objective """
objective = Maximize(sum_entries(mul_elemwise(A_ROLES, X)))

""" Solve """
problem = Problem(objective, constraints)
problem.solve()

""" Output """
print(problem.status, problem.value)
print('assignments: \n' + str(np.array(np.round(X.value), dtype=int)))  # pretty-printing of ASSIGNMENTS
print('a-roles taken: \n' + str(np.array(np.round(mul_elemwise(A_ROLES, X).value), dtype=int)))  # pretty-printing of hitted A-roles

输出

('optimal', 4.000000000087978)
assignments: 
[[1 0 0 0 0]
 [0 0 0 0 1]
 [0 0 0 0 0]
 [0 1 0 0 0]
 [0 0 1 0 0]
 [0 0 0 1 0]]
a-roles taken: 
[[1 0 0 0 0]
 [0 0 0 0 1]
 [0 0 0 0 0]
 [0 1 0 0 0]
 [0 0 0 0 0]
 [0 0 0 1 0]]

有可能实现一种方法,同时坚持线性编程(在实践和理论上具有较低的计算复杂度),采用@ user29970提到的一些想法,尽管我对其中一些有点持怀疑态度描述。

我也懒惰,MIP方法在数值稳定性方面至少更好。

答案 1 :(得分:0)

这是加权二分图(人和角色)的最大匹配。您可以使用匈牙利语算法:https://en.wikipedia.org/wiki/Hungarian_algorithm

scipy.optimize中有一个实现,这里是调用它的代码:

import scipy.optimize
prefs = ['AAUWU', 'UUWWA', 'WAUWW', 'AAUUU', 'AUWUW', 'UAAAW']
cost = {'A': 0, 'U': 999999, 'W': 1, 'D': 0}
mat = [[cost[P] for P in pref+'D'*(len(prefs)-len(pref))] for pref in prefs]
agent, task = scipy.optimize.linear_sum_assignment(mat)
print('\n'.join('{} -> {} ({})'.format(A,T,prefs[A][T]) for A,T in zip(agent, task) if T < len(prefs[0])))

输出:

0 -> 3 (W)
1 -> 4 (A)
2 -> 1 (A)
4 -> 0 (A)
5 -> 2 (A)