我正在尝试对范围进行Van der Corput采样,但是具有自定义分辨率。
例如,考虑以25的分辨率对范围[0, 100]
进行采样。这将需要在[0, 25, 50, 75, 100]
进行采样,并且如果我们遵循类似于Van der Corput的序列,则类似:{ {1}}。
Van der Corput算法的每个“遍”将范围迭代地划分为上遍的大小[0, 100, 50, 25, 75]
(2分,然后是3、5、9、17 ...)。因此,如果我的最小分辨率为1/2
,则我需要24
(在这种情况下为9)样本,而不是2^n + 1
样本才能获得所需的分辨率。
是否有任何方法可以产生我正在寻找的解决方案?
答案 0 :(得分:2)
首先,我认为您的序列有一个小缺陷,100
从来都不是该序列的一部分。
binary decimal binary reverse
0.0 0.0 0.0
0.1 0.5 1.0
0.01 0.25 10.0
0.11 0.75 11.0
0.001 0.125 100.0
0.101 0.625 101.0
0.011 0.375 110.0
0.111 0.875 111.0
二进制反向镜像“ 二进制点”上的数字。所以在这里我们看到这实际上只是一个二进制计数器。
我们可以使用该逻辑为给定范围的i
和l
分别整数下限和上限,来生成序列的第u
个元素:
def vdc_seq(i, l, u):
v = 0
p = 0
d = u - l
while i:
v <<= 1
if i & 1:
v += d
i >>= 1
p += 1
if p:
v += (1 << p-1)
return l + v >> p
例如:
>>> list(map(partial(vdc_seq, l=0, u=100), range(9)))
[0, 50, 25, 75, 13, 63, 38, 88, 6]
通过替换以下内容,我们可以在此处轻松使用浮点数:
def vdc_seq(i, l, u):
v = 0
p = 1
d = u - l
while i:
v <<= 1
if i & 1:
v += d
i >>= 1
p <<= 1
return l + v / p
第 2 k + 1 -1 元素的“分辨率”为 2 -k ,因此对于给定的最小分辨率m
,我们可以确定何时停止,并生成如下列表:
from functools import partial
def vdc_seq_list_min(l, u, m):
n = 2 * (u - l + m - 1) // m - 1
return map(partial(vdc_seq, l=l, u=u), range(n))
例如:
>>> list(vdc_seq_list_min(0, 100, 24))
[0, 50, 25, 75, 13, 63, 38, 88, 6]
>>> list(vdc_seq_list_min(0, 100, 10))
[0, 50, 25, 75, 13, 63, 38, 88, 6, 56, 31, 81, 19, 69, 44, 94, 3, 53, 28, 78]