Python 确定一组组合的最高分数

Python 确定一组组合的最高分数,python,algorithm,Python,Algorithm,我在用python编程 我有以下表格的数据: (A, B, C, D, E, F, G, H, I) 此数据段与分数相关联,例如: scores: (A, B, C, D) = .99 (A, B, C, E) = .77 (A, B, E) = .66 (G,) = 1 (I,) = .03 (H, I) = .55 (I, H) = .15 (E, F, G) = .79 (B,) = .93 (A, C)

我在用python编程

我有以下表格的数据:

(A, B, C, D, E, F, G, H, I)
此数据段与分数相关联,例如:

scores:

    (A, B, C, D) = .99
    (A, B, C, E) = .77
    (A, B, E) = .66
    (G,) = 1
    (I,) = .03
    (H, I) = .55
    (I, H) = .15
    (E, F, G) = .79
    (B,) = .93
    (A, C) = .46
    (D,) = .23
    (D, F, G) = .6
    (F, G, H) = .34
    (H,) = .09
    (Y, Z) = 1
我们可以得到该数据的分数,如下所示:

A B C E + D F G + H I = .77 * .6 * .55 = 0.2541
另一种可能性是:

A B C D + E F G + H + I = .99 * .79 * .09 * .03 = 0.00211167
因此,第一个组合的得分较高

我想写一个算法来为高于最高可能分数的数据建立。数据的成员不应重复超过一次。换言之:

A B C E + E F G + D + H I 
无效。你会建议我如何着手解决这个问题

谢谢

巴里

编辑: 我应该澄清一下(H,I)!=(I,H)和(I,H)不是ABCDEFGHI的子段,而是ABIHJ的子段。
我应该提到的另一件事是,分数是一个非常大的集合(百万),我们计算分数的部分的平均长度约为10。此外,我计算分数的方式将来可能会改变。也许我想把这些子段加起来,取平均值而不是倍数,谁知道呢。。。因此,最好将计算可能组合的代码与实际分数计算分开。目前,我倾向于认为itertools.compositions可能提供了一个很好的起点。

这听起来像是一个伪装的NP完全问题,是。这意味着您可能需要遍历所有的可能性才能得到精确的解决方案

即使。。。等待您的值介于0和1之间。也就是说,结果只能得到较小的,最多保持相等。因此,解决方案很简单:获取具有最高值的单个组,然后完成。(我知道这可能不是您想要的,但您可能需要添加另一个条件,例如,必须使用所有元素……)

暴力手段的开始:

import operator

segment_scores = {(A, B, C, D): .99, (A, B, C, E): .77} #...

def isvalid(segments):
    """returns True if there are no duplicates
    for i in range(len(segments)-1):
        for element in segments[i]:
            for j in range(len(segments)-i-1):
              othersegment = segments[j+i+1]
              if element in othersegment:
                return False
    return True

    better way:
    """
    flattened = [item for sublist in segments for item in sublist]
    # http://stackoverflow.com/questions/952914/making-a-flat-list-out-of-list-of-lists-in-python
    return len(set(flattened)) == len(flattened)

def getscore(segments):
    """
    p = 1.0
    for segment in segments:
      p *= segment_scores[segment]
    return p

    better way:
    """
    return reduce(operator.mul, [segment_scores[segment] for segment in segments])
现在,创建所有2^(num段)段的可能组合,检查每个段是否有效,如果有效,则计算分数,同时保留当前获胜者及其高分。只是一个起点

好的,这只是另一个更新:这里有很多优化空间,特别是因为您正在进行乘法(我假设现在您必须使用每个元素)

  • 由于您的总分从未增加,因此您可以删除任何低于当前高分的探索路径[segment0,segment1],因为您只能获得任何segment2的作品

  • 如果您不只是迭代所有的可能性,而是从搜索包含第一个段的所有段列表开始(通过递归搜索除第二个段外还包含第二个段的所有段列表等),您可以在第一个段和第二个段无效时立即中断,也就是说,无需探索分组(A、B、C、D)和(A、B、C、D、e)的所有可能性

  • 由于相乘会造成伤害,因此尝试最小化分段的数量可能是一个合适的启发式方法,因此从高分的大分段开始


通过使用递归强制(对于顺序中的每个段,我们递归地使用该段查找最佳分数,而不使用该段查找最佳分数。如果剩余项目没有可能的段组合,则分配0分):


首先,我建议为有意义的片段指定一个唯一的符号

然后,你可能需要这些符号的组合(或者可能是排列,我相信你比我更了解你的问题),以及一个“合法段组合”函数,你可以用它来排除不好的可能性——基于一个矩阵,其中哪些冲突,哪些不冲突

>>> import itertools
>>> itertools.combinations([1,2,3,4], 2)
<itertools.combinations object at 0x7fbac9c709f0>
>>> list(itertools.combinations([1,2,3,4], 2))
[(1, 2), (1, 3), (1, 4), (2, 3), (2, 4), (3, 4)]
>>>
导入itertools >>>itertools.组合([1,2,3,4],2) >>>列表(itertools.组合([1,2,3,4],2)) [(1, 2), (1, 3), (1, 4), (2, 3), (2, 4), (3, 4)] >>>
然后最大化通过合法分段组合的有效可能性()。然后,您可以将问题作为一个问题来解决,在哪里为每个数据点分配一个序列。

对于上述数据,最佳分数大概是0.430155?我想“所有元素都必须使用”是有意的,是的。我的帖子以某种方式实时地反映了我的理解过程,因此我提出了这个问题。也许我应该在写作前多想想,但现在我决定就这样离开……;)令人钦佩的代码。但是,在哪里可以确保不重复使用同一物品?对于当前的数据集来说,这可能不是一个问题,而且不太可能,因为您希望使用更少的段,而不是更多的段,但在某些情况下,您可能会违反该条件。所以我建议只在片段的所有元素都在itemssegment_scores=(('A','B'),1),('B','C'),1),('C'),0.5的情况下才通过第一条路径。啊,我明白你的意思了。很容易修复(现在已经修复)。
>>> import itertools
>>> itertools.combinations([1,2,3,4], 2)
<itertools.combinations object at 0x7fbac9c709f0>
>>> list(itertools.combinations([1,2,3,4], 2))
[(1, 2), (1, 3), (1, 4), (2, 3), (2, 4), (3, 4)]
>>>