在这个问题中,您需要保留一些虚拟输出(如@Gene 指出的那样,拒绝采样),在这些输出上重复执行的实验。
我在这里提供了两个实现。 第一个是次优的,但更容易理解。 第二个更理想,但有点困难。最后,我尝试概述证明并链接到 Math StackExchange 答案。
第一种方法 -
第 1 步 - 运行 rand1() x + 1 次。
第 2 步 - 检查输出是否为 one-hot。我的意思是,只有 1 个 x + 1 运行导致 1 和所有其他 0。如果不是这样,请重复第 1 步。否则转到第 3 步。
第 3 步 - 打印索引 1 作为输出。
python 代码将如下所示 -
def randx(x):
choice = -1
while choice == -1:
for i in range(0, x+1):
c = rand1()
if c == 1 and choice == -1:
choice = i
elif c == 1 and choice != -1:
choice = -1
break
第二种方法 -
当然,第一种方法是次优的。你可以做得更好,但它需要更多的代码。假设我们想要在 x+1 值(0 到 x)之间进行预测。您至少需要进行实验k = ceil(log(x+1)) 次。现在,每个结果都有1 / 2^k的相等概率。
在这些2^k 的可能性中,将一些分配给数字(由于我们选择了k,您将看到您可以将一个数字分配给至少一半的可能性)。调用其他可能性 dummy 输出。
当您获得 dummy 输出时,您只需重复实验即可。如果不这样做,则输出与该输出对应的数字。
例如,如果 x = 4,x + 1 = 5。因此我们需要k = 3。分配 0, 1, 2, 3, 4 它们的二进制表示(000 到 101),并将剩余的 3 保留为哑元。伪代码如下所示,
function randx(x):
choice = -1
runs = ceil(log(x+1))
while choice == -1:
output = 0
for i in range(0, runs):
output += pow(2, i)*rand1()
if output <= x:
choice = output
为什么会这样?
我们给所有的数字赋予相等的可能事件。如果这些事件都没有发生,我们只是重复这个实验。如果你看得到一个数字i的总概率,
Let p = 1 / 2^k
Let q = 1 - (x+1)*p
Total probability of getting i = p + q*p + q*q*p + q*q*q*p ...
= p/(1-q)
= 1/(x+1)
Hence this sums up to 1 / (x+1).
有关 MathJax 的更完整解释,请参阅https://math.stackexchange.com/questions/2356/is-it-possible-to-split-coin-flipping-3-ways