アプローチ
これは、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 アプローチの方が優れています。