alias采样:一种时间复杂度为O(1)的采样方法

一、算法原理:

参考博客:https://blog.csdn.net/haolexiao/article/details/65157026

论文地址:http://citeseerx.ist.psu.edu/viewdoc/download?doi=10.1.1.675.8158&rep=rep1&type=pdf

二、代码实现:

import numpy as np

def alias_table(prob_table):
    n = len(prob_table)
    prob_norm = np.array(prob_table) * n
    small, large = [], []
    for i, prob in enumerate(prob_norm):
        if prob < 1:
            small.append(i)
        else:
            large.append(i)
            
    accept, alias = [0] * n, [0] * n
    while small and large:
        small_idx, large_idx = small.pop(), large.pop()
        #存放第i列对应的事件i的概率;
        accept[small_idx] = prob_norm[small_idx]
        #存放不是事件i的另外事件的标号;
        alias[small_idx] = large_idx
        
        prob_norm[large_idx] = prob_norm[large_idx] - (1 - prob_norm[small_idx])
        if prob_norm[large_idx] < 1.0:
            small.append(large_idx)
        else:
            large.append(large_idx)
    
    while small:
        small_idx = small.pop()
        accept[small_idx] = 1
        
    while large:
        large_idx = large.pop()
        accept[large_idx] = 1
    return accept, alias
            
def alias_sample(accept, alias):
    n = len(accept)
    i = int(np.random.random() * n)
    r = np.random.random()
    if r < accept[i]:
        return i
    else:
        return alias[i]

prob_table = [1/2,1/3,1/12,1/12]
ac, a = alias_table(prob_table)
i = alias_sample(ac, a)
print(i)

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值