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

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/video/2.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 按不同顺序生成itertools.product_Python_Algorithm_Itertools - Fatal编程技术网

Python 按不同顺序生成itertools.product

Python 按不同顺序生成itertools.product,python,algorithm,itertools,Python,Algorithm,Itertools,我有一些经过排序/评分的参数列表。我想生成可能的参数组合(笛卡尔积)。但是,如果参数的数量很大,那么很快(非常快!!)就会变成一个非常大的数字。基本上,我想做一个笛卡尔积,但要早点停下来 import itertools parameter_options = ['1234', '123', '1234'] for parameter_set in itertools.product(*parameter_opt

我有一些经过排序/评分的参数列表。我想生成可能的参数组合(笛卡尔积)。但是,如果参数的数量很大,那么很快(非常快!!)就会变成一个非常大的数字。基本上,我想做一个笛卡尔积,但要早点停下来

import itertools
parameter_options = ['1234',
                     '123',
                     '1234']
for parameter_set in itertools.product(*parameter_options):
    print ''.join(parameter_set)
生成:

111
112
113
114
121
122
123
124
131
132
133
134
...
我想生成(或类似的内容):

因此,如果我提前停止,我至少会得到几个“好”的参数集,其中一组好的参数主要来自列表中的早期。这个特定的顺序可以,但我对任何改变“下一个排列”选择顺序的技术都感兴趣。我希望生成的早期结果能够将列表前面的大多数项放在前面,但并不真正关心解决方案是先生成113项还是122项,还是先生成211项还是112项


我的计划是在生成一定数量的排列后停止(可能是10K左右?取决于结果)。因此,如果数量少于截止值,最终应生成所有数量。最好每个组合只生成一次。

此解决方案可能不是最好的,因为它会将每个组合短暂地放入内存中,但确实有效。对于大型数据集,可能需要一点时间

import itertools
import random
count = 100  # the (maximum) amount of results
results = random.sample(list(itertools.product(*parameter_options)), count)

for parameter_set in results:
    print "".join(parameter_set)

这将为您提供一个随机顺序的产品列表。

如果您将输出视为对输出空间的图形遍历,我认为您可以按照您想要的顺序获得结果。您需要最接近的第一次遍历,而
itertools.product
函数是深度优先遍历

试着这样做:

import heapq

def nearest_first_product(*sequences):
    start = (0,)*len(sequences)
    queue = [(0, start)]
    seen = set([start])
    while queue:
        priority, indexes = heapq.heappop(queue)
        yield tuple(seq[index] for seq, index in zip(sequences, indexes))
        for i in range(len(sequences)):
            if indexes[i] < len(sequences[i]) - 1:
                lst = list(indexes)
                lst[i] += 1
                new_indexes = tuple(lst)
                if new_indexes not in seen:
                    new_priority = sum(index * index for index in new_indexes)
                    heapq.heappush(queue, (new_priority, new_indexes))
                    seen.add(new_indexes)
通过更改代码中
new\u priority
的计算,您可以获得一系列稍有不同的顺序。当前版本使用平方笛卡尔距离作为优先级,但如果需要,可以使用其他值(例如,包含序列中的值,而不仅仅是索引中的值)

如果您不太关心
(1,1,3)
是否在
(1,2,2)
之前(只要它们都在
(1,1,2)
(1,2,1)
(2,1,1)
之后),您可能会进行宽度优先遍历,而不是最近的第一次遍历。这会更简单一些,因为您可以使用常规队列(如
collections.deque
)而不是优先级队列


这种图遍历所使用的队列意味着该代码使用了一些内存。然而,与在整理结果之前必须提前生成结果相比,内存量要少得多。使用的最大内存与结果空间的表面积成正比,而不是其体积。

您的问题有点模棱两可,但阅读您的评论和其他答案,您似乎想要一个笛卡尔乘积实现,它执行广度搜索而不是深度搜索

最近我有了与您相同的需求,但也要求它不会在内存中存储中间结果。这对我来说非常重要,因为我处理大量参数(因此是一个非常大的笛卡尔积),任何存储值或进行递归调用的实现都是不可行的。正如你在问题中所说,这似乎也是你的情况

由于我没有找到满足此要求的答案,因此我采用了以下解决方案:

def product(*sequences):
    '''Breadth First Search Cartesian Product'''
    # sequences = tuple(tuple(seq) for seqin sequences)

    def partitions(n, k):
        for c in combinations(range(n+k-1), k-1):
            yield (b-a-1 for a, b in zip((-1,)+c, c+(n+k-1,)))

    max_position = [len(i)-1 for i in sequences]
    for i in range(sum(max_position)):
        for positions in partitions(i, len(sequences)):
            try:
                yield tuple(map(lambda seq, pos: seq[pos], sequences, positions))
            except IndexError:
                continue
    yield tuple(map(lambda seq, pos: seq[pos], sequences, max_position))
就速度而言,该生成器一开始工作正常,但在最新结果中开始变慢。因此,尽管这个实现有点慢,但它作为一个生成器工作,不使用内存,也不提供重复的值

正如我在@Blckknght-answer中提到的,这里的参数也必须是序列(可下标和长度定义的iterables)。但是您也可以通过取消第一行的注释来绕过这个限制(牺牲一点内存)。如果使用生成器/迭代器作为参数,这可能很有用


我希望我已经帮助了您,如果这有助于解决您的问题,请告诉我。

您到底想要什么?那个特定的顺序,或者只是其他的顺序?那个特定的顺序会很好,但我对任何改变“下一个排列”选择顺序的技术感兴趣。我希望早期生成的结果中大多数项位于列表的最前面,但我并不关心解决方案是先生成113项还是122项,或者是先生成211项还是112项。您最终做了什么?好吧,OP有时希望最终处理所有项,所以我可能会使用
random.shuffle
,不是随机的。示例,因此您仍然拥有详尽的数据。也就是说,如果输入的大小有很大的增长,那么将其全部保存在内存中可能是一个大问题。我看不出他是怎么说的。但如果他想这样做,那么他最好在那一刻按顺序去做。OP说,“所以如果我早点停下来,…”(强调补充)。听起来像是他们想要运行的处理,直到他们点击
Ctrl-C
或其他什么,生成结果,直到他们完成或终止它。我能理解这种解释。我认为这更像是“如果我让程序这么做”。希望OP很快会发表评论,所以我们有一个澄清。我绝对不想产生所有的结果。如果只有20个参数,每个参数只有2个选项,那将超过100万个元素。我建议对代码进行编辑,因为它有一些小错误,不允许正常运行。还有一点很重要,那就是这个实现有一个重要的限制:这个产品函数不能与生成器一起使用,具体来说,它只能与可下标且具有定义长度的可重用项一起使用。如果您不太关心内存,可以绕过这个问题,在开头添加这一行
sequences=tuple(序列中的seq的tuple(seq)
@martindelafuentesavedra:Yep,感谢您的编辑(我看到它挂起时批准了它)。我已经修好了
for tup in nearest_first_product(range(1, 5), range(1, 4), range(1, 5)):
    print(tup)

(1, 1, 1)
(1, 1, 2)
(1, 2, 1)
(2, 1, 1)
(1, 2, 2)
(2, 1, 2)
(2, 2, 1)
(2, 2, 2)
(1, 1, 3)
(1, 3, 1)
(3, 1, 1)
(1, 2, 3)
(1, 3, 2)
(2, 1, 3)
(2, 3, 1)
(3, 1, 2)
(3, 2, 1)
(2, 2, 3)
(2, 3, 2)
(3, 2, 2)
(1, 3, 3)
(3, 1, 3)
(3, 3, 1)
(1, 1, 4)
(2, 3, 3)
(3, 2, 3)
(3, 3, 2)
(4, 1, 1)
(1, 2, 4)
(2, 1, 4)
(4, 1, 2)
(4, 2, 1)
(2, 2, 4)
(4, 2, 2)
(3, 3, 3)
(1, 3, 4)
(3, 1, 4)
(4, 1, 3)
(4, 3, 1)
(2, 3, 4)
(3, 2, 4)
(4, 2, 3)
(4, 3, 2)
(3, 3, 4)
(4, 3, 3)
(4, 1, 4)
(4, 2, 4)
(4, 3, 4)
def product(*sequences):
    '''Breadth First Search Cartesian Product'''
    # sequences = tuple(tuple(seq) for seqin sequences)

    def partitions(n, k):
        for c in combinations(range(n+k-1), k-1):
            yield (b-a-1 for a, b in zip((-1,)+c, c+(n+k-1,)))

    max_position = [len(i)-1 for i in sequences]
    for i in range(sum(max_position)):
        for positions in partitions(i, len(sequences)):
            try:
                yield tuple(map(lambda seq, pos: seq[pos], sequences, positions))
            except IndexError:
                continue
    yield tuple(map(lambda seq, pos: seq[pos], sequences, max_position))