我正在寻找一种方法,让群体中最好的人群组合起来。让我描述一下情况。
假设我们有人A,B,C和D.此外,我们有1,2,3,4和3组。两者都是例子,可以更少或更多。每个人都给每个人一个评级。因此,例如A率B a 3,C a 2等等。每个人也对每个组进行评分。 (比如说等级为0-5)。现在我需要某种算法来将这些人均匀地分布在群组上,同时让他们尽可能地保持快乐(例如:他们应该在一个高级组中,有高级人员)。现在我知道人们不可能成为最好的团队(他们评为5分组),但我需要他们为整个团队提供最好的解决方案。
我认为这是一个棘手的问题,如果有人可以向我提供有关此类问题的更多信息,或者帮助我找到我正在寻找的算法,我会很高兴。
谢谢!
修改 我看到很多很棒的答案,但这个问题对我来说太大了,也无法正确解决。然而,到目前为止发布的答案给了我一个很好的起点,进一步研究这个主题。非常感谢!
答案 0 :(得分:1)
问题是NP难:你可以从最大三角形包装中减少,即在图形中找到至少k个顶点不相交的三角形,到有k个大小为3的组的版本,没有人关心哪个他所在的小组,喜欢0或1的所有人。所以即使这个非常特殊的情况也很难。
要解决这个问题,我会尝试使用ILP:拥有二进制变量g_ik,表示人员i在组k中,并且有约束以确保一个人只在一个组中并且一个组具有适当的大小。此外,二进制变量t_ijk指示人i和j在组k中一起(由t_ijk <= 0.5 g_ik + 0.5 g_jk确保)和二进制变量t_ij,其指示i和j在任何组中一起(由t_ij&lt确保) ; = sum_k t_ijk)。然后,您可以在这些约束下最大化幸福函数。
这个ILP有很多变量,但现代求解器非常好,这种方法很容易实现。
答案 1 :(得分:1)
可能的方法是steepest ascent hill climbing [SAHC]
首先,我们将定义我们的效用函数(让它为u
)。它可以是所有群体中总幸福感的总和。
接下来,我们定义我们的'世界':S is the group of all possible partitions
。
对于S的每个合法分区,我们定义:
next(s)={all possibilities moving one person to a different group}
现在我们要做的就是随机重启运行SAHC:
1. best<- -INFINITY
2. while there is more time
3. choose a random partition as starting point, denote it as s.
4. NEXT <- next(s)
5. if max{ U(NEXT) } < u(s): //s is the top of the hill
5.1. if u(s) > best: best <- u(s) //if s is better then the previous result - store it.
5.2. go to 2. //restart the hill climbing from a different random point.
6. else:
6.1. s <- max{ NEXT }
6.2. goto 4.
7. return best //when out of time, return the best solution found so far.
它是anytime algorithm,意味着它会得到更好的结果,因为你给它更多的时间来运行,并且最终[在无限时间]它会找到最佳结果。
答案 2 :(得分:1)
这是optimization问题的一个例子。这是一个非常好的 用很好的方法来研究问题的类型来解决它们。读 Programming Collective Intelligence更好地解释了它 比我。
基本上,任何一种优化问题都有三个部分。
现在问题可以说是找到产生的解决方案 得分最高。要做到这一点,首先需要提出一种格式 表示评分函数可以的可能解决方案 得分了。假设有6个人(0-5)和3个组(0-2),这个python数据结构 会工作,并将成为一个可能的解决方案:
output = [
[0, 1],
[2, 3],
[4, 5]
]
第0组和第1组被放入组0中,第2组和第3组被放入组1中 上。要获得此解决方案,我们需要了解输入和规则 计算输出。输入可以由此数据表示 结构:
input = [
[0, 4, 1, 3, 4, 1, 3, 1, 3],
[5, 0, 1, 2, 1, 5, 5, 2, 4],
[4, 1, 0, 1, 3, 2, 1, 1, 1],
[2, 4, 1, 0, 5, 4, 2, 3, 4],
[5, 5, 5, 5, 0, 5, 5, 5, 5],
[1, 2, 1, 4, 3, 0, 4, 5, 1]
]
列表中的每个列表代表该人给出的评级。对于 例如,在第一行中,人0将评级0给予人0(你 不能评价自己),4对1对1对1对2,3对3,4对4和 1对人5.然后他或她对组0-2,3,1和3进行评分 分别
以上是给定输入的有效解决方案的示例。怎么做 我们得分了?这个没有在问题中指明,只有那个 需要“最佳”组合,因此我会随意决定 解决方案的得分是每个人幸福的总和。每 通过加入他或她的评级来确定人的幸福感 组中每个人的平均评分, 排除此人本身。
以下是评分函数:
N_GROUPS = 3
N_PERSONS = 6
def score_solution(input, output):
tot_score = 0
for person, ratings in enumerate(input):
# Check what group the person is a member of.
for group, members in enumerate(output):
if person in members:
# Check what rating person gave the group.
group_rating = ratings[N_PERSONS + group]
# Check what rating the person gave the others.
others = list(members)
others.remove(person)
if not others:
# protect against zero division
person_rating = 0
else:
person_ratings = [ratings[o] for o in others]
person_rating = sum(person_ratings) / float(len(person_ratings))
tot_score += group_rating + person_rating
return tot_score
对于给定的解决方案,它应该返回37.0的分数。怎么办 我们要做的是生成有效的输出,同时跟踪哪一个 在我们满意之前是最好的:
from random import choice
def gen_solution():
groups = [[] for x in range(N_GROUPS)]
for person in range(N_PERSONS):
choice(groups).append(person)
return groups
# Generate 10000 solutions
solutions = [gen_solution() for x in range(10000)]
# Score them
solutions = [(score_solution(input, sol), sol) for sol in solutions]
# Sort by score, take the best.
best_score, best_solution = sorted(solutions)[-1]
print 'The best solution is %s with score %.2f' % (best_solution, best_score)
在我的电脑上运行它会产生:
The best solution is [[0, 1], [3, 5], [2, 4]] with score 47.00
显然,你可能认为随机选择这是一个非常愚蠢的想法 生成解决方案以解决问题,它就是。有很多 更复杂的方法来生成模拟等解决方案 退火或遗传优化。但它们都建立在同样的基础之上 如上所述的框架。