Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/algorithm/12.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_List_Cartesian Product_Branch And Bound - Fatal编程技术网

Python 如何在一定条件下组合大列表(再次列表)

Python 如何在一定条件下组合大列表(再次列表),python,algorithm,list,cartesian-product,branch-and-bound,Python,Algorithm,List,Cartesian Product,Branch And Bound,我试图解决一个来自生物学领域的问题,在这个领域中,我必须结合每个大元素的局部次优解,这样每个子粒子都是唯一的。问题是,可能性可能会扩大到+4.000个局部次优解决方案,以及+30.000个元素。笛卡尔乘积不是一个选项,因为组合列表是一个n*m*p*。。。如果没有itertools以外的算法,这个问题是不可能解决的 一般模式为: [ [ [a,b,c],[d,e,a],[f], ...], [ [f,e,t],[a,b,t],[q], ...], [ [a,e,f],[],[p], .

我试图解决一个来自生物学领域的问题,在这个领域中,我必须结合每个大元素的局部次优解,这样每个子粒子都是唯一的。问题是,可能性可能会扩大到+4.000个局部次优解决方案,以及+30.000个元素。笛卡尔乘积不是一个选项,因为组合列表是一个
n*m*p*
。。。如果没有
itertools
以外的算法,这个问题是不可能解决的

一般模式为:

[
  [ [a,b,c],[d,e,a],[f], ...],
  [ [f,e,t],[a,b,t],[q], ...],
  [ [a,e,f],[],[p], ... up to 4.000],
  ... up to 30.000
]
[[a,b,c],[d,e,a],[f],…],一组元素的次优解#一,

我想尽快找到

  • 首先:一个解决方案,这意味着每个元素的一个次优解决方案的组合(可以包括空白列表),这样就不会有重复。例如[[a,b,c],[f,e,t][p]]

  • 第二个:所有兼容的解决方案

我知道这是一个开放的问题,但我需要一些指导或一般算法来面对这个问题,如果我有什么可以开始进一步调查

我在剩下的实验工作中使用python,但是我对其他语言持开放态度

我们可以从一个基本的解算器开始,该解算器在总次优和列表数量方面处理较少的可能性

最好的

编辑1

一个非常简短的真实示例:

[[[1,2,3][1,2,4],[1,2,5],[5,8]],
[[1,3][7,8],[6,1]],
[[]],
[[9,10][7,5],[6,9],[6,10]]]
最佳解决方案(来自第#行):


可以在这里看到

这里有一些算法。您可以使用itertools对所有可能的组合进行暴力搜索,非常简单:

from itertools import product, chain

def get_compatible_solutions(subsolutions):
    for sol in product(*subsolutions):
        if len(set(chain.from_iterable(sol))) == sum(map(len, sol)):
            yield sol

# Test
example = [
    [[1, 2, 3], [1, 2, 4], [1, 2, 5], [5, 8]],
    [[1, 3], [7, 8], [6, 1]],
    [[]],
    [[9, 10], [7, 5], [6, 9], [6, 10]]
]

# Get one solution
print(next(get_compatible_solutions(example)))
# ([1, 2, 3], [7, 8], [], [9, 10])

# Get all solutions
print(*get_compatible_solutions(example), sep='\n')
# ([1, 2, 3], [7, 8], [], [9, 10])
# ([1, 2, 3], [7, 8], [], [6, 9])
# ([1, 2, 3], [7, 8], [], [6, 10])
# ([1, 2, 4], [7, 8], [], [9, 10])
# ([1, 2, 4], [7, 8], [], [6, 9])
# ([1, 2, 4], [7, 8], [], [6, 10])
# ([1, 2, 5], [7, 8], [], [9, 10])
# ([1, 2, 5], [7, 8], [], [6, 9])
# ([1, 2, 5], [7, 8], [], [6, 10])
# ([5, 8], [1, 3], [], [9, 10])
# ([5, 8], [1, 3], [], [6, 9])
# ([5, 8], [1, 3], [], [6, 10])
# ([5, 8], [6, 1], [], [9, 10])
另一种可能是一次递归搜索一行。这将比笛卡尔积探索更少的候选解决方案,因为一旦从搜索路径中排除次优解决方案,将不会处理包括它在内的任何组合

def get_compatible_solutions(subsolutions):
    current = [None] * len(subsolutions)
    seen = set()
    yield from _get_compatible_solutions_rec(subsolutions, current, 0, seen)

def _get_compatible_solutions_rec(subsolutions, current, i, seen):
    if i >= len(subsolutions):
        yield tuple(current)
    else:
        for subsol in subsolutions[i]:
            if any(s in seen for s in subsol):
                continue
            seen.update(subsol)
            current[i] = subsol
            yield from _get_compatible_solutions_rec(subsolutions, current, i + 1, seen)
            seen.difference_update(subsol)

这里有几个算法。您可以使用itertools对所有可能的组合进行暴力搜索,非常简单:

from itertools import product, chain

def get_compatible_solutions(subsolutions):
    for sol in product(*subsolutions):
        if len(set(chain.from_iterable(sol))) == sum(map(len, sol)):
            yield sol

# Test
example = [
    [[1, 2, 3], [1, 2, 4], [1, 2, 5], [5, 8]],
    [[1, 3], [7, 8], [6, 1]],
    [[]],
    [[9, 10], [7, 5], [6, 9], [6, 10]]
]

# Get one solution
print(next(get_compatible_solutions(example)))
# ([1, 2, 3], [7, 8], [], [9, 10])

# Get all solutions
print(*get_compatible_solutions(example), sep='\n')
# ([1, 2, 3], [7, 8], [], [9, 10])
# ([1, 2, 3], [7, 8], [], [6, 9])
# ([1, 2, 3], [7, 8], [], [6, 10])
# ([1, 2, 4], [7, 8], [], [9, 10])
# ([1, 2, 4], [7, 8], [], [6, 9])
# ([1, 2, 4], [7, 8], [], [6, 10])
# ([1, 2, 5], [7, 8], [], [9, 10])
# ([1, 2, 5], [7, 8], [], [6, 9])
# ([1, 2, 5], [7, 8], [], [6, 10])
# ([5, 8], [1, 3], [], [9, 10])
# ([5, 8], [1, 3], [], [6, 9])
# ([5, 8], [1, 3], [], [6, 10])
# ([5, 8], [6, 1], [], [9, 10])
另一种可能是一次递归搜索一行。这将比笛卡尔积探索更少的候选解决方案,因为一旦从搜索路径中排除次优解决方案,将不会处理包括它在内的任何组合

def get_compatible_solutions(subsolutions):
    current = [None] * len(subsolutions)
    seen = set()
    yield from _get_compatible_solutions_rec(subsolutions, current, 0, seen)

def _get_compatible_solutions_rec(subsolutions, current, i, seen):
    if i >= len(subsolutions):
        yield tuple(current)
    else:
        for subsol in subsolutions[i]:
            if any(s in seen for s in subsol):
                continue
            seen.update(subsol)
            current[i] = subsol
            yield from _get_compatible_solutions_rec(subsolutions, current, i + 1, seen)
            seen.difference_update(subsol)


嗨,欢迎来到苏。请您提供一些小样本输入、预期输出以及您的方法中的可复制代码样本(如果有的话)?这样一行应该没有重复值?LazyCoder,谢谢您的快速回答。现在在答案的正文中找到一个例子,也是一个最佳结果。Basilisk,所需的解决方案从每个“大”列表中有一个元素,这些列表之间的条件是所有元素都是唯一的。一个元素是指一行(列表或数组)或一个数字?我看不到这里的模式对不起,这些列表之间的关系如何?条件是元素是唯一的?你为什么不使用6?是uniqueHi,欢迎来到SO。请您提供一些小样本输入、预期输出以及您的方法中的可复制代码样本(如果有的话)?这样一行应该没有重复值?LazyCoder,谢谢您的快速回答。现在在答案的正文中找到一个例子,也是一个最佳结果。Basilisk,所需的解决方案从每个“大”列表中有一个元素,这些列表之间的条件是所有元素都是唯一的。一个元素是指一行(列表或数组)或一个数字?我看不到这里的模式对不起,这些列表之间的关系如何?条件是元素是唯一的?你为什么不使用6?这是唯一的,我现在无法测试代码,但暴力解决方案是我正在使用的解决方案,没有像n*m那样工作,所以很快就有了数十亿种可能性。你认为递归的一个可以面对这个问题吗?非常感谢您的回答。@HardinSalvor我运行了一个合成示例,每个元素最多有5个次优解,每个次优解在[0,99]中最多包含5个不同的整数,总共有10项。兼容解的数量为675601,第一个算法探索了9765625个候选完整解,耗时15.3秒,而第二个算法探索了1666535个候选部分解,耗时1.6秒。有一个重要的加速,但不是几个数量级。@HardinSalvor不同次优解决方案元素(即
a
b
c
…)的数量的通常范围是多少。我在可能性小于10亿的情况下进行了测试并快速运行。然而,我们的情况是在那个疯狂的范围内(这就是为什么我不知道组合是否是答案)。每行的实际范围通常会扩展到数千个次优解决方案。我现在无法测试代码,但暴力解决方案是我正在使用的解决方案,并且没有像n*m那样工作,因此很快就有数十亿种可能性。你认为递归的一个可以面对这个问题吗?非常感谢您的回答。@HardinSalvor我运行了一个合成示例,每个元素最多有5个次优解,每个次优解在[0,99]中最多包含5个不同的整数,总共有10项。兼容解的数量为675601,第一个算法探索了9765625个候选完整解,耗时15.3秒,而第二个算法探索了1666535个候选部分解,耗时1.6秒。有一个重要的加速,但不是几个数量级。@HardinSalvor不同次优解决方案元素(即
a
b
c
…)的数量的通常范围是多少。我在可能性小于10亿的情况下进行了测试并快速运行。然而,我们的情况是在那个疯狂的范围内(这就是为什么我不知道组合是否是答案)。每行的实际范围通常扩展到数千个次优解。