我有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
的索引,将一个索引元组返回到a
和b
,如下所示:
f(2) # (1,0)
f(4) # (1,1)
同样,它不必是Z字形算法的线性索引。任何在无限生成器上生成笛卡尔积的算法都可以作为基础。
答案 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)
生成笛卡尔积的各种方法都是相同程序的变体:
将产品元组划分为可数无数的有限大小的块;
依次在每个块中生成元组。
“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个元组,您:
对于 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