实际上,N非常大,比如1000。我想要随机采样这个2^1000整数的大空间,但我需要生成类似于随机行走的东西,因为我所考虑的应用程序只能通过翻转一位从一个数字跳到另一个数字。
这让我想起了分形 - 沿着Julia集合的边界或类似的东西。
如果N为1000,则使用一个2^500 x 2^500的分形位图(显然不要提前生成它 - 您可以按需推导每个像素,并且大多数像素不需要)。每个像素移动都是沿着像素之间的边界线向上、向下、向左或向右的一个像素,就像简单的位图跟踪算法一样。只要您从位图的边缘开始,您应该迟早会返回到位图的边缘 - 沿着特定的“颜色”边界始终应该给出没有自交的闭合曲线,如果您查看该分形的无界版本。
当然,位图的x和y轴坐标将需要“格雷编码” - 有点像超大型Karnaugh地图。跟踪中的每个步骤(向上、向下、向左或向右的一个像素)相当于一个位图坐标中的单比特更改,因此在随机行走的结果值中的一个位上也会发生单比特更改。
编辑
我刚意识到有一个问题。边界越皱,你在跟踪中遇到选择方向的点的可能性就越大,例如...
* | .
---+---
. | *
无论您从哪个方向进入这个点,都有三种出路可选。选择另外两个中的错误之一可能会使您返回到此点,因此这是一个可能的自交点和可能的重复。您可以消除“继续朝同一方向前进”的选择 - 无论您转向哪个方向,应该保持相同的边界颜色在您追踪的边界路径的左右两侧 - 但这仍然留下了两个方向的选择。
我认为可以通过在分形中至少使用三种颜色,并始终将同一颜色保持在边界的某一特定侧(相对于追踪方向)来消除问题。虽然可能有一个“只要分形不太皱”的限制。
最后的解决方法是记录此选择可用的点。如果您返回到相同的点,请返回并选择另一种选择。
当像这样的算法:
seed()
i = random(0, n)
repeat:
i ^= >> (i % bitlen)
yield i
如果要返回一个随机的整数序列,每个整数之间相差1位,那么需要一个巨大的数组来进行回溯,以确保数字的唯一性。此外,随着回溯密度的增加,您的运行时间将呈指数级增长,因为在序列中每增加一个数字,命中新的且不重复的数字的几率就会降低。
为了减少时间和空间,可以尝试其中之一:
使用Bloom过滤器可以大大减少唯一性回溯所需的空间(和时间)。
由于Bloom过滤器偶尔会产生误报,因此在您的序列中会出现一定比例的错误检测到的重复项(因此被跳过)。
虽然使用Bloom过滤器可以减少空间和时间,但您的运行时间仍将呈指数级增长...
s
(s
是你的平面/立方体/超立方体的边长)之间的n
个(n
为你的平面/立方体/超立方体的维度)随机数。
希尔伯特曲线不仅可以消除回溯的需求,还可以让序列运行在每个数字的O(1)
时间内(与使用回溯相比,后者会使您的运行时间呈指数级增加...)n
维分布。
注:您可能会在此处获得更好的答案:StackExchange 的 CSTheory (或者不会,参见评论)
rand()
将生成相同的序列,被认为是伪随机。不过你说得好。我忘记在我的答案中提到一种可能的播种方式了。现在已经添加了。基本上是用随机种子进行随机位移移位,并用随机种子进行封装。因此,虽然它总是会生成相同的模式,但实际数字序列的顺序高度取决于种子的移位距离和分布的性质。 - Regexident