
import numpy
import random
import scipy.special as special
 
 
class BayesianSmoothing(object):
    def __init__(self, alpha, beta):
        self.alpha = alpha
        self.beta = beta
 
    def sample(self, alpha, beta, num, imp_upperbound):
        sample = numpy.random.beta(alpha, beta, num)
        print(sample)
        I = []
        C = []
        for clk_rt in sample:
            imp = imp_upperbound # imp_upperbound广告展示次数上限，imp广告随机展示次数
            clk = imp * clk_rt
            I.append(imp)
            C.append(clk)
        return I, C
 
    def update(self, imps, clks, iter_num, epsilon):
        for i in range(iter_num):
            new_alpha, new_beta = self.__fixed_point_iteration(imps, clks, self.alpha, self.beta)
            if abs(new_alpha-self.alpha)<epsilon and abs(new_beta-self.beta)<epsilon:
                break
            self.alpha = new_alpha
            self.beta = new_beta
 
    def __fixed_point_iteration(self, imps, clks, alpha, beta):
        numerator_alpha = 0.0
        numerator_beta = 0.0
        denominator = 0.0
 
        for i in range(len(imps)):
            numerator_alpha += (special.digamma(clks[i]+alpha) - special.digamma(alpha))
            numerator_beta += (special.digamma(imps[i]-clks[i]+beta) - special.digamma(beta))
            denominator += (special.digamma(imps[i]+alpha+beta) - special.digamma(alpha+beta))
 
        return alpha*(numerator_alpha/denominator), beta*(numerator_beta/denominator)
 
 

def p():
    bs = BayesianSmoothing(1, 1)
    I, C = bs.sample(500, 500, 1000, 10000)
    print(I, C)
    bs.update(I, C, 1000, 0.0000000001)
    print(bs.alpha, bs.beta)


if __name__ == '__main__':
    p()

