从线性索引获取下标到无限生成器的产品

时间:2018-02-04 20:12:30

标签: python algorithm

我有N个无限生成器。我已经知道如何使用这些无限生成器的笛卡尔积,因为有几种方法列出here(" zig-zag","扩展方块"等)。我并不真正关心使用哪种方法作为我真正想要的基础:我想将"索引转换为笛卡尔积?"进入原始生成器" 的索引元组,而不实际迭代笛卡尔积,直到那一点。我很清楚我实际上无法索引到生成器。没关系,因为我需要的只是索引本身。基本上,我想要here所描述的相同的东西,但适用于无限生成器。

如果我们考虑一个具体的例子,这将是最容易理解的。我们只考虑两个生成器(N=2)并让它们都为itertools.count(),这样生成器的索引和生成器的值都是相同的。

from itertools import count
a = count()  # 0, 1, 2, ...
b = count()  # 0, 1, 2, ...

让我们假设我使用之字形算法,因为作者非常友好地在PyPI上使用它。

from infinite import product
p = product(a, b)  # (0,0), (0,1), (1,0), (0,2), (1,1), (2,0), ...

我想要一个函数,给定p的索引,将一个索引元组返回到ab,如下所示:

f(2)  # (1,0)
f(4)  # (1,1)

同样,它不必是Z字形算法的线性索引。任何在无限生成器上生成笛卡尔积的算法都可以作为基础。

2 个答案:

答案 0 :(得分:4)

您正试图反转pairing function。您提供的“之字形”算法是Cantor pairing function(由参数顺序更改),由f(x, y) = (x+y)(x+y+1)/2 + y给出,它具有如下反转。

如果f^-1(z) = (x, y),那么

w = floor((sqrt(8z+1)-1)/2)
t = w(w+1)/2
y = z-t
x = w-y

您可以看到完整派生的维基百科链接。

答案 1 :(得分:0)

生成笛卡尔积的各种方法都是相同程序的变体:

  1. 将产品元组划分为可数无数的有限大小的块;

  2. 依次在每个块中生成元组。

  3. “zigzag”方法和Cantor的函数,例如,通过索引总和的块:

    For integer i = 0 to infinity
        generate all tuples with sum(component_indexes) == i
    

    “扩展方法”是:

    For integer i = 0 to infinity
        generate all tuples with max(component_indexes) == i
    

    等...

    要直接找到任何这些方法的第k个元组,您:

    1. SMALLER(i)为编号小于 i 的块中的元组数。找到 i 的最大值 SMALLER(i)< = k 。这是包含第k个元组的块的数量。
    2. 使用块号 i 获取(k-SMALLER(i))元组(从零开始)。
    3. 对于 N 维度中的“扩展方块”方法,例如, SMALLER(i)= i ^ N - 所有组件小于的元组数,所以 i = floor(Nth_root(k))。设 r = k - i ^ N ,然后找到 rth 元组(例如,按词汇顺序),其中max component等于 k

      直接索引的最简单的类产品是位交错。在该方案中,产品索引的二进制扩展中的连续位以循环方式分配给组件索引。在python中它看起来像这样:

      def getProductTerm(dimensions, index):
          ret=[0]*dimensions
          bit=0
          while index>0:
              ret[dimensions-1-(bit%dimensions)]+=(index&1)<<(bit/dimensions)
              index >>= 1
              bit+=1
          return ret
      

      您可以在此处试用:https://ideone.com/0dTMU3