如何从2个列表中确定最佳组合

时间:2011-08-16 13:10:39

标签: algorithm combinations distribution rating

我正在寻找一种方法,让群体中最好的人群组合起来。让我描述一下情况。

假设我们有人A,B,C和D.此外,我们有1,2,3,4和3组。两者都是例子,可以更少或更多。每个人都给每个人一个评级。因此,例如A率B a 3,C a 2等等。每个人也对每个组进行评分。 (比如说等级为0-5)。现在我需要某种算法来将这些人均匀地分布在群组上,同时让他们尽可能地保持快乐(例如:他们应该在一个高级组中,有高级人员)。现在我知道人们不可能成为最好的团队(他们评为5分组),但我需要他们为整个团队提供最好的解决方案。

我认为这是一个棘手的问题,如果有人可以向我提供有关此类问题的更多信息,或者帮助我找到我正在寻找的算法,我会很高兴。

谢谢!

修改 我看到很多很棒的答案,但这个问题对我来说太大了,也无法正确解决。然而,到目前为止发布的答案给了我一个很好的起点,进一步研究这个主题。非常感谢!

3 个答案:

答案 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)

在确定这是NP-Hard问题之后,我建议作为启发式解决方案:人工智能工具。

可能的方法是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更好地解释了它 比我。

基本上,任何一种优化问题都有三个部分。

  1. 问题解决功能的输入
  2. 问题解决功能输出解决方案
  3. 评估解决方案最佳程度的评分函数 得分吧。
  4. 现在问题可以说是找到产生的解决方案 得分最高。要做到这一点,首先需要提出一种格式 表示评分函数可以的可能解决方案 得分了。假设有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
    

    显然,你可能认为随机选择这是一个非常愚蠢的想法 生成解决方案以解决问题,它就是。有很多 更复杂的方法来生成模拟等解决方案 退火或遗传优化。但它们都建立在同样的基础之上 如上所述的框架。