可变分辨率范德科普特序列

时间:2019-05-28 20:14:57

标签: python algorithm sampling

我正在尝试对范围进行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样本才能获得所需的分辨率。

是否有任何方法可以产生我正在寻找的解决方案?

1 个答案:

答案 0 :(得分:2)

首先,我认为您的序列有一个小缺陷,100从来都不是该序列的一部分。 应为 0、50、25、75,...

如果我们看一下数字的二进制分数,那么范德Corput序列就会显示出一种有趣的模式。从本质上讲,它可以归结为:

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

二进制反向镜像“ 二进制点”上的数字。所以在这里我们看到这实际上只是一个二进制计数器。

我们可以使用该逻辑为给定范围的il分别整数下限和上限,来生成序列的第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]