itertools产品加速


问题内容

我使用itertools.product来生成长度为13的4个元素的所有可能变体。4和13可以是任意的,但实际上,我得到4 ^
13的结果,这是很多的。我需要将结果作为一个Numpy数组,当前需要执行以下操作:

  c = it.product([1,-1,np.complex(0,1), np.complex(0,-1)], repeat=length)
  sendbuf = np.array(list(c))

中间插入一些简单的分析代码,看起来第一行几乎是瞬时的,而转换为列表然后转换为Numpy数组大约需要3个小时。有没有办法使它更快?我可能忽略了很明显的东西。

谢谢!


问题答案:

该NumPy的等效的itertools.product()numpy.indices(),但它只会让你的形式0的范围内的产品,…,K-1:

numpy.rollaxis(numpy.indices((2, 3, 3)), 0, 4)
array([[[[0, 0, 0],
         [0, 0, 1],
         [0, 0, 2]],

        [[0, 1, 0],
         [0, 1, 1],
         [0, 1, 2]],

        [[0, 2, 0],
         [0, 2, 1],
         [0, 2, 2]]],


       [[[1, 0, 0],
         [1, 0, 1],
         [1, 0, 2]],

        [[1, 1, 0],
         [1, 1, 1],
         [1, 1, 2]],

        [[1, 2, 0],
         [1, 2, 1],
         [1, 2, 2]]]])

对于特殊情况,您可以使用

a = numpy.indices((4,)*13)
b = 1j ** numpy.rollaxis(a, 0, 14)

(由于阵列太大,因此无法在32位系统上运行。从我可以测试的大小推断,它应该在不到一分钟的时间内运行。)

EIDT:只需提一下:对的调用numpy.rollaxis()或多或少是装饰性的,以获得与相同的输出itertools.product()。如果您不关心索引的顺序,则可以忽略它(但是只要您没有任何后续操作都可以将数组转换为连续数组,它还是很便宜的。)

编辑2:要获得确切的类似物

numpy.array(list(itertools.product(some_list, repeat=some_length)))

您可以使用

numpy.array(some_list)[numpy.rollaxis(
    numpy.indices((len(some_list),) * some_length), 0, some_length + 1)
    .reshape(-1, some_length)]

这变得完全不可读-告诉我是否应该进一步解释它了:)