Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/algorithm/11.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python 快速查找具有最大不同元素总数的列表的子集_Python_Algorithm_Optimization - Fatal编程技术网

Python 快速查找具有最大不同元素总数的列表的子集

Python 快速查找具有最大不同元素总数的列表的子集,python,algorithm,optimization,Python,Algorithm,Optimization,给定一个元组列表,我想找到列表的子集,它最大化不同整数值的数量,而不重复任何整数 列表如下所示: x = [ [(1,2,3), (8,9,10), (15,16)], [(2,3), (10,11)], [(9,10,11), (17,18,19), (20,21,22)], [(4,5), (11,12,13), (18,19,20)] ] 内部元组始终是顺序的-->(1,2,3)或(15,16),但它们可以是

给定一个元组列表,我想找到列表的子集,它最大化不同整数值的数量,而不重复任何整数

列表如下所示:

x = [
         [(1,2,3), (8,9,10), (15,16)],
         [(2,3), (10,11)],
         [(9,10,11), (17,18,19), (20,21,22)],
         [(4,5), (11,12,13), (18,19,20)]
    ]
内部元组始终是顺序的-->(1,2,3)或(15,16),但它们可以是任意长度

在这种情况下,预期回报为:

maximized_list = [
                  [(1, 2, 3), (8, 9, 10), (15, 16)], 
                  [(4, 5), (11, 12, 13), (18, 19, 20)]
                 ]
这是有效的,因为在每种情况下:

  • x的每个内部列表保持不变
  • 存在最大数量的不同整数(本例中为16个)
  • 不重复任何整数
  • 如果存在多个有效解决方案,则应在列表中返回所有解决方案

    我对这一点有一个天真的实现,主要基于我之前提出的stackoverflow问题,该问题的格式没有它可能的好():


    上面提到的函数似乎给出了正确的结果,但没有缩放。我需要接受带有几千个列表(可能多达上万个)的x值,因此需要一个优化算法。

    以下是关于基数的子列表的最大子集的解。它的工作原理是将每个子列表展平,在子列表之间构建一个交集列表,然后以深度优先的方式搜索解决方案空间,搜索元素最多的解决方案(即最大“权重”)

    def最大化_distinct(子列表):
    子集=[{x代表tup中的x的子列表中的tup}代表子列表中的子列表]
    定义相交(子集):
    返回{i for i,枚举(子集)中的sset如果子集&sset}
    交点=[子集中子集的交点(子集)]
    权重=[子集中的子集的len(子集)]
    池=集合(范围(len(子集)))
    最大值集,搜索最大值(池、交点、权重)
    return[最大集合中i的子列表[i]
    def搜索_max(池、交叉点、权重):
    如果不是池:返回[],0
    最大设置=最大重量=无
    对于池中的num:
    next_pool={x代表池中的x-如果x>num,则相交[num]
    设置\u ID,权重=搜索\u最大值(下一个\u池,交点,权重)
    如果不是最大设置或最大重量<重量+重量[num]:
    最大设置,最大权重=[num]+设置ID,权重+权重[num]
    返回最大设置,最大重量
    

    通过保持丢弃的“权重”(子列表的基数之和)的运行总数,并在搜索空间的分支超过目前为止的最大解(即最小丢弃权重)时修剪该分支,可以进一步优化此代码。但是,除非您遇到性能问题,否则这可能会超出其价值,对于一小部分列表,计算开销将超过修剪的速度。

    内部元组的意义是什么?似乎每个列表可能只是一个数字列表,而不是一对数字?内部元组是否总是n和n+1?元组是否总是在列表中排序?@Carlos如果这使问题更容易解决,可以假设元组总是排序的。@Carlos内部元组总是顺序的,但并不总是n和n+1单独存在。为了反映这一点,我改变了问题。通过上面的示例x值来最大化_distinct(),我在search_max()中的最后一个“if语句”上得到了一个错误:“@RyanLague是的,我重新排序了if语句中的条件,因为
    not max_set
    除了第一次迭代之外,其余都失败了,但没有考虑类型错误。将参数切换回原位或使用
    0
    而不是
    None
    将修复此问题。编辑以将if语句还原为工作状态
    import itertools
    
    def maximize(self, x):
        max_ = 0
        possible_patterns = []
    
        for i in range(1, len(x)+1):
            b = itertools.combinations(x, i)
    
            for combo in b:
                all_ints = tuple(itertools.chain(*itertools.chain(*combo)))
                distinct_ints = tuple(set(all_ints))
    
                if sorted(all_ints) != sorted(distinct_ints):
                    continue
                else:
                    if len(all_ints) >= max_:
                        if len(all_ints) == max_:
                            possible_patterns.append(combo)
                            new_max = len(all_ints)
                        elif len(all_ints) > max_:
                            possible_patterns = [combo]
                            new_max = len(all_ints)
                        max_ = new_max
    
        return possible_patterns
    
    def maximize_distinct(sublists):
        subsets = [{x for tup in sublist for x in tup} for sublist in sublists]
    
        def intersect(subset):
            return {i for i, sset in enumerate(subsets) if subset & sset}
    
        intersections = [intersect(subset) for subset in subsets]
        weights = [len(subset) for subset in subsets]
    
        pool = set(range(len(subsets)))
        max_set, _ = search_max(pool, intersections, weights)
        return [sublists[i] for i in max_set]
    
    def search_max(pool, intersections, weights):
        if not pool: return [], 0
    
        max_set = max_weight = None
        for num in pool:
            next_pool = {x for x in pool - intersections[num] if x > num}
            set_ids, weight = search_max(next_pool, intersections, weights)
    
            if not max_set or max_weight < weight + weights[num]:
                max_set, max_weight = [num] + set_ids, weight + weights[num]
        return max_set, max_weight