def __init__(self, rate=1): """Create Exp(rate) distribution. :param rate First shape parameter of exp """ assert rate > 0 self.rate = rate self.UG = UniformDist() super().__init__(ContinuousSpace(0, np.inf, open_brackets=False))
def __init__(self, shape=1, scale=1): """Create Ga(shape,scale) distribution. :param shape Shape of Ga(shape,scale) :param scale Scale of Ga(shape,scale) """ self.shape = shape self.scale = scale self.UG = UniformDist() if shape >= 1: self.NG = NormalDist() super().__init__(ContinuousSpace(0, np.inf, open_brackets=False))
def __init__(self, rate=1): """Create Poi(rate) distribution. :param rate The rate parameter. """ # save params assert 0 < rate self.rate = rate # create distribution for sampling self.UG = UniformDist() super().__init__(DiscreteSpace(0, np.inf))
def __init__(self, mean=0, var=1): """Create N(mean, var) distribution. :param mean Center of the gaussian :param var Variance around the center. """ self.mean = mean self.var = var # create random generators self.EG = ExpDist() self.UG = UniformDist() super().__init__(ContinuousSpace(-np.inf, np.inf))
def __init__(self, p=0.5): """Create Ber(p) distribution. :param p Probability that random var is true """ # save params assert 0 <= p <= 1 self.p = p # create distribution for sampling self.UG = UniformDist() super().__init__(DiscreteSpace([0, 1]))
def __init__(self, a=1, b=3): """Create U(K) distribution. :param rate The rate parameter. """ # save params assert b >= a self.a = a self.b = b # create distribution for sampling self.UG = UniformDist() super().__init__(DiscreteSpace(a, b + 1))
def __init__(self, loc=1, scale=1): """Creates Gumbel(loc,scale) distribution. :param loc Location of the distribution. :param scale Scale of the distribution """ # save params self.loc = loc self.scale = scale # create generator self.UG = UniformDist() super().__init__(ContinuousSpace(-np.inf, np.inf))
def __init__(self, v = 1, loc = 0, scale = 1): """Create t(v,loc,scale) distribution. :param v Degrees of Freedom """ # save params self.v = v self.loc = loc self.scale = scale # create generator self.UG = UniformDist() super().__init__(ContinuousSpace(-np.inf, np.inf))
def __init__(self, shape=1, scale=1): """Creates Pareto(shape,scale) distribution. :param shape Shape of the distribution. :param scale Scale of the distribution """ # save params self.shape = shape self.scale = scale # create generator self.UG = UniformDist() super().__init__(ContinuousSpace(0, np.inf, open_brackets=False))
def __init__(self, n = 1, p = 0.5): """Create Geom(p) distribution. :param n Which should be summed :param p Probability that random var is true """ # save params assert 0 <= p <= 1 assert 1 <= n self.p = p self.n = n # create distribution for sampling self.UG = UniformDist() super().__init__(DiscreteSpace(1, np.inf))
class ExpDist(ProbDist): """Simple exponential distribution.""" def __init__(self, rate=1): """Create Exp(rate) distribution. :param rate First shape parameter of exp """ assert rate > 0 self.rate = rate self.UG = UniformDist() super().__init__(ContinuousSpace(0, np.inf, open_brackets=False)) def expectation(self): """Calculates the expectations for that distribution. :returns The expectation of the distribution""" return 1 / self.rate def moment(self, k): """Calculates the k-th moment for that distribution. :param k which moment to calc :returns The k-th moment of the distribution""" return m.factorial(k) / self.rate**k def var(self): """Calculates the variance for that distribution. :returns The variance of the distribution""" return 1 / self.rate**2 def c_pdf(self, x): """This method calculates the density Exp(x|rate). :param x Which value should be evaluated. :returns The probability this element occurs. """ rate = self.rate return rate * np.exp(-rate * x) def sample(self, num_samples=1): """Generate random numbers from Exp(rate) by using inverse-transform method. :param num_samples How many random numbers should be generated. :returns A random number from Exp(rate). """ # generate result list and uniform samples rate = self.rate U = self.UG.sample(num_samples) return (-1 / rate) * np.log(U)
class DUniformDist(ProbDist): """Sample U(K) distribution.""" def __init__(self, a=1, b=3): """Create U(K) distribution. :param rate The rate parameter. """ # save params assert b >= a self.a = a self.b = b # create distribution for sampling self.UG = UniformDist() super().__init__(DiscreteSpace(a, b + 1)) def expectation(self): """Calculates the expectations for that distribution. :returns The expectation of the distribution""" a = self.a b = self.b return (a + b) / 2 def var(self): """Calculates the variance for that distribution. :returns The variance of the distribution""" a = self.a b = self.b return ((b - a) * (b - a + 2)) / 12 def sample(self, num_samples=1): """Generate random numbers from Poi(rate). :param num_samples How many random numbers should be generated. :returns Random numbers x ~ Poi(rate). """ U = self.UG.sample(num_samples) X = np.floor() return def __density(self, x): """This method calculates the mass Poi(rate). :param x Which value should be evaluated. :returns The probability this element occurs. """ z = np.power(self.rate, x) / m.factorial(x) return z * np.exp(-self.rate)
class GeometricDist(ProbDist): """Simple Geom(p) distribution.""" def __init__(self, n = 1, p = 0.5): """Create Geom(p) distribution. :param n Which should be summed :param p Probability that random var is true """ # save params assert 0 <= p <= 1 assert 1 <= n self.p = p self.n = n # create distribution for sampling self.UG = UniformDist() super().__init__(DiscreteSpace(1, np.inf)) def expectation(self): """Calculates the expectations for that distribution. :returns The expectation of the distribution""" return 1 / self.p def var(self): """Calculates the variance for that distribution. :returns The variance of the distribution""" return (1 - self.p) / self.p ** 2 def sample(self, num_samples = 1): """Generate random numbers from Geom(p). :param num_samples How many random numbers should be generated. :returns Random numbers x ~ Geom(p). """ U = self.UG.sample(num_samples) X = np.floor(np.log(U) / np.log(1 - self.p)) return X def __density(self, x): """This method calculates the mass Geom(p). :param x Which value should be evaluated. :returns The probability this element occurs. """ f = np.power(1 - self.p, x - 1) * self.p return f
class BernDist(ProbDist): """Simple bernoulli distribution.""" def __init__(self, p=0.5): """Create Ber(p) distribution. :param p Probability that random var is true """ # save params assert 0 <= p <= 1 self.p = p # create distribution for sampling self.UG = UniformDist() super().__init__(DiscreteSpace([0, 1])) def expectation(self): """Calculates the expectations for that distribution. :returns The expectation of the distribution""" return self.p def var(self): """Calculates the variance for that distribution. :returns The variance of the distribution""" return self.p * (1 - self.p) def sample(self, num_samples=1): """Generate random numbers from Ber(p). :param num_samples How many random numbers should be generated. :returns Random numbers x ~ Ber(p). """ # create gamma distributed vars U = self.UG.sample(num_samples) for k in range(num_samples): U[k] = int(U[k] <= self.p) return U def __density(self, x): """This method calculates the mass Ber(x|p). :param x Which value should be evaluated. :returns The probability this element occurs. """ assert np.all([np.logical_or(np.equal(x, 0), np.equal(x, 1))]) return np.power(self.p, x) * np.power(1 - self.p, np.subtract(1, x))
def __init__(self, alpha, A): """Create DPH(alpha, A) distribution. :param alpha probability vector 1xm :param A mxm matrix such that (I - A) is invertible. """ # save params assert np.sum(alpha) == 1 assert np.shape(A)[0] == np.shape(A)[1] == len(alpha) self.alpha = np.expand_dims(alpha, 0) self.A = np.array(A) self.m = np.shape(A)[1] # create distribution for sampling self.UG = UniformDist() super().__init__(DiscreteSpace(1, np.inf))
def __init__(self, n=20, r=150, N=300): """Create Hyp(n, r, N) distribution. :param n offset vars :param r binomaial offset :param N biggest number. """ # save params self.r = r self.n = n self.N = N # generate upper and lower bound lb = np.maximum(0, r + n - N) ub = np.minimum(n, r) # create distribution for sampling self.UG = UniformDist() super().__init__(DiscreteSpace(lb, ub + 1))
class ParetoDist(ProbDist): """Simple Pareto distribution.""" def __init__(self, shape=1, scale=1): """Creates Pareto(shape,scale) distribution. :param shape Shape of the distribution. :param scale Scale of the distribution """ # save params self.shape = shape self.scale = scale # create generator self.UG = UniformDist() super().__init__(ContinuousSpace(0, np.inf, open_brackets=False)) def expectation(self): """Calculates the expectations for that distribution. :returns The expectation of the distribution""" return 1 / (self.scale * (self.shape - 1)) def var(self): """Calculates the variance for that distribution. :returns The variance of the distribution""" shape = self.shape scale = self.scale return shape / (scale**2 * (shape - 1)**2 * (shape - 2)) def sample(self, num_samples=1): """Generate random numbers from Pareto(shape,scale). :param num_samples How many random numbers should be generated. :returns Random numbers x ~ Pareto(shape,scale). """ # shortcut shape = self.shape scale = self.scale # sample data U = self.UG.sample(num_samples) X = U**(-1 / shape) - 1 return scale * X def c_pdf(self, x): """This method calculates the density Pareto(shape,scale). :param x Which value should be evaluated. :returns The probability that this element occurs. """ # shortcut shape = self.shape scale = self.scale # update x return shape * scale * (1 + np.multiply(scale, x))**(-(shape + 1))
class StudentsTDist(ProbDist): """Simple student-t distribution.""" def __init__(self, v = 1, loc = 0, scale = 1): """Create t(v,loc,scale) distribution. :param v Degrees of Freedom """ # save params self.v = v self.loc = loc self.scale = scale # create generator self.UG = UniformDist() super().__init__(ContinuousSpace(-np.inf, np.inf)) def expectation(self): """Calculates the expectations for that distribution. :returns The expectation of the distribution""" return self.loc def var(self): """Calculates the variance for that distribution. :returns The variance of the distribution""" return self.scale ** 2 * (self.v / (self.v - 2)) def sample(self, num_samples=1): """Generate random numbers from t(v,loc,scale). :param num_samples How many random numbers should be generated. :returns Random numbers from t(v,loc,scale). """ # shortcut v = self.v loc = self.loc scale = self.scale elements = np.empty(num_samples) # create samples for k in range(num_samples): # iterate till found found = False while not found: # generate some samples u1 = self.UG.sample() u2 = self.UG.sample() # set X and V if u1 < 0.5: X = 1 / (4 * u1 - 1) V = u2 / X ** 2 else: X = 4 * u1 - 3 V = u2 # acceptance check if V < 1 - abs(X) / 2 or V < (1 + (X ** 2) / v) ** (-(v+1) / 2): elements[k] = X found = True return scale * elements + loc def c_pdf(self, x): """This method calculates the density t(v,loc,scale). :param x What values should be evaluated. :returns The probability this element occurs. """ # shortcut v = self.v loc = self.loc scale = self.scale # update x xn = np.subtract(x, loc) / scale z = m.gamma((v + 1) / 2) / (np.sqrt(v * m.pi) * m.gamma(v / 2)) X = (1 + np.square(xn) / v) ** (-(v+1) / 2) return (z * X) / scale
class GumbelDist(ProbDist): """Simple Gumbel distribution.""" def __init__(self, loc=1, scale=1): """Creates Gumbel(loc,scale) distribution. :param loc Location of the distribution. :param scale Scale of the distribution """ # save params self.loc = loc self.scale = scale # create generator self.UG = UniformDist() super().__init__(ContinuousSpace(-np.inf, np.inf)) def expectation(self): """Calculates the expectations for that distribution. :returns The expectation of the distribution""" return self.scale * 0.577216 + self.loc def var(self): """Calculates the variance for that distribution. :returns The variance of the distribution""" return (self.scale**2) * (m.pi**2 / 6) def sample(self, num_samples=1): """Generate random numbers from Gumbel(loc, scale) by using acceptance rejection distributions. :param num_samples How many random numbers should be generated. :returns Random numbers x ~ Gumbel(loc, scale). """ # shortcut loc = self.loc scale = self.scale # sample data U = self.UG.sample(num_samples) X = -np.log(-np.log(U)) return scale * X + loc def c_pdf(self, x): """This method calculates the density Dist(x). :param x Which value should be evaluated. :returns The probability that this element occurs. """ # shortcut loc = self.loc scale = self.scale # update x xn = np.subtract(x, loc) / scale f = np.exp(-xn - np.exp(-xn)) / scale return f
class WeibullDist(ProbDist): """Simple Weibull distribution.""" def __init__(self, shape=1, loc=1, scale=1): """Creates Weib(shape,loc,scale) distribution. :param shape Shape of the distribution. :param loc Location of the distribution. :param scale Scale of the distribution """ # save params self.shape = shape self.loc = loc self.scale = scale # create generator self.UG = UniformDist() super().__init__(ContinuousSpace(0, np.inf, open_brackets=False)) def expectation(self): """Calculates the expectations for that distribution. :returns The expectation of the distribution""" return (self.scale**-1) * m.gamma(1 + self.shape**-1) + self.loc def var(self): """Calculates the variance for that distribution. :returns The variance of the distribution""" return self.scale ** -2 \ * (m.gamma(1 + 2 * self.shape ** -1) - m.gamma(1 + self.shape ** -1) ** 2) def sample(self, num_samples=1): """Generate random numbers from Weib(shape,loc,scale). :param num_samples How many random numbers should be generated. :returns Random numbers x ~ Weib(shape,loc,scale). """ # shortcut shape = self.shape loc = self.loc scale = self.scale # some sampling U = self.UG.sample(num_samples) X = 1 / scale * (-np.log(U))**(1 / shape) return scale * X + loc def c_pdf(self, x): """This method calculates the density Weib(shape,loc,scale). :param x Which value should be evaluated. :returns The probability that this element occurs. """ assert x > 0 # shortcut shape = self.shape loc = self.loc scale = self.scale xn = np.subtract(x, loc) / scale # update x ft = shape * xn**(shape - 1) * np.exp(-xn**shape) return ft / scale
class WaldDist(ProbDist): """Simple Wald distribution.""" def __init__(self, loc = 0, scale = 1): """Creates Wald(loc,scale) distribution. :param loc Location of the distribution. :param scale Scale of the distribution """ # save params self.loc = loc self.scale = scale # create generator self.NG = NormalDist() self.UG = UniformDist() super().__init__(ContinuousSpace(0, np.inf)) def expectation(self): """Calculates the expectations for that distribution. :returns The expectation of the distribution""" return self.loc def var(self): """Calculates the variance for that distribution. :returns The variance of the distribution""" return self.loc ** 3 / self.scale def sample(self, num_samples = 1): """Generate random numbers from Wald(loc,scale). :param num_samples How many random numbers should be generated. :returns Random numbers x ~ Wald(loc,scale). """ # shortcut loc = self.loc scale = self.scale # some sampling W = self.NG.sample(num_samples) Y = W ** 2 Z = loc + (loc ** 2 * Y / 2 * scale) + (loc / 2 * scale) * np.sqrt(4 * loc * scale * Y + loc ** 2 * Y ** 2) X = Z # sample uniforms bound = loc / (loc + Z) B = self.UG.sample(num_samples) # iterate for k in range(num_samples): if B[k] > bound: X[k] = loc ** 2 / Z[k] return X def c_pdf(self, x): """This method calculates the density Wald(loc,scale). :param x Which value should be evaluated. :returns The probability that this element occurs. """ assert x > 0 # shortcut loc = self.loc scale = self.scale # update x z = np.sqrt(scale / (2 * np.pi * np.power(x, 3))) b = np.exp(-0.5 * (scale / loc ** 2) * (np.subtract(x, loc) ** 2) / x) return z * b
class GammaDist(ProbDist): """Simple gamma distribution.""" def __init__(self, shape=1, scale=1): """Create Ga(shape,scale) distribution. :param shape Shape of Ga(shape,scale) :param scale Scale of Ga(shape,scale) """ self.shape = shape self.scale = scale self.UG = UniformDist() if shape >= 1: self.NG = NormalDist() super().__init__(ContinuousSpace(0, np.inf, open_brackets=False)) def expectation(self): """Calculates the expectations for that distribution. :returns The expectation of the distribution""" return self.shape / self.scale def var(self): """Calculates the variance for that distribution. :returns The variance of the distribution""" return self.shape / self.scale**2 def sample(self, num_samples=1): """Generate random numbers from Ga(shape,scale) by using acceptance rejection distributions. :param num_samples How many random numbers should be generated. :returns Random numbers x ~ Ga(shape,scale). """ # extract vars shape = self.shape # when the shape is bigger than 1 elements = self.rand_shp_gt_1(num_samples) \ if shape >= 1 else \ self.rand_shp_st_1(num_samples) return elements / self.scale def rand_shp_gt_1(self, num_samples): """Creates random variables, if gamma has shape bigger or equal to one. Marsaglia and Tsang's method from [1] implemented underneath. :param num_samples How many random numbers should be generated. :returns Random numbers x ~ Ga(shape,scale). Refs: [1] https://dl.acm.org/citation.cfm?id=358414. """ # some pre settings elements = np.empty(num_samples) shape = self.shape d = shape - 1 / 3 c = 1 / m.sqrt(9 * d) # create all samples for k in range(num_samples): # generate normal and unif z = self.NG.sample() u = self.UG.sample() v = (1 + c * z)**3 # first check while z <= -(1 / c) or m.log( u) > 0.5 * z**2 + d - d * v + d * m.log(v): z = self.NG.sample() u = self.UG.sample() v = (1 + c * z)**3 elements[k] = d * v return elements def rand_shp_st_1(self, num_samples): """Creates random variables, if gamma has shape smaller than one. Best's method from [1] implemented underneath. :param num_samples How many random numbers should be generated. :returns Random numbers x ~ Ga(shape,scale). Refs: [1] https://link.springer.com/article/10.1007/BF02280789. """ # some pre settings elements = np.empty(num_samples) shape = self.shape # some pre settings d = 0.07 + 0.75 * m.sqrt(1 - shape) b = 1 + m.exp(-d) * (shape / d) # create all samples for k in range(num_samples): found = False # repeat till found while not found: # two uniform ones u1 = self.UG.sample() u2 = self.UG.sample() v = b * u1 if v <= 1: # shorthand x = d * v**(1 / shape) # acceptance check if u2 <= (2 - x) / (2 + x) or u2 <= m.exp(-x): elements[k] = x found = True else: # shorthand x = -m.log(d * (b - v) / shape) y = x / d # acceptance check if u2 * (shape + y * (1 - shape)) <= 1 or u2 < y**(shape - 1): elements[k] = x found = True return elements def c_pdf(self, x): """This method calculates the density Ga(x|shape,scale). :param x Which value should be evaluated. :returns The probability this element occurs. """ shape = self.shape scale = self.scale z = scale**shape / m.gamma(shape) xa = np.power(x, (shape - 1)) ex = np.exp(np.multiply(-scale, x)) return z * xa * ex
class PoissonDist(ProbDist): """Simple Poi(rate) distribution.""" def __init__(self, rate=1): """Create Poi(rate) distribution. :param rate The rate parameter. """ # save params assert 0 < rate self.rate = rate # create distribution for sampling self.UG = UniformDist() super().__init__(DiscreteSpace(0, np.inf)) def expectation(self): """Calculates the expectations for that distribution. :returns The expectation of the distribution""" return self.rate def var(self): """Calculates the variance for that distribution. :returns The variance of the distribution""" return self.rate def sample(self, num_samples=1): """Generate random numbers from Poi(rate). :param num_samples How many random numbers should be generated. :returns Random numbers x ~ Poi(rate). """ X = np.empty(num_samples) for k in range(len(X)): # starting n = 1 a = 1 Un = self.UG.sample() a = a * Un # iterate over while a >= np.exp(-self.rate): n = n + 1 Un = self.UG.sample() a = a * Un X[k] = n - 1 return X def __density(self, x): """This method calculates the mass Poi(rate). :param x Which value should be evaluated. :returns The probability this element occurs. """ z = np.power(self.rate, x) / m.factorial(x) return z * np.exp(-self.rate)
class NormalDist(ProbDist): """Simple gaussian distribution.""" def __init__(self, mean=0, var=1): """Create N(mean, var) distribution. :param mean Center of the gaussian :param var Variance around the center. """ self.mean = mean self.var = var # create random generators self.EG = ExpDist() self.UG = UniformDist() super().__init__(ContinuousSpace(-np.inf, np.inf)) def expectation(self): """Calculates the expectations for that distribution. :returns The expectation of the distribution""" return self.mean def var(self): """Calculates the variance for that distribution. :returns The variance of the distribution""" return self.var def sample(self, num_samples=1): """Generate random numbers from N(mean, var) by using an acceptance rejection algorithm using Exp(1) and U(0,1). :param num_samples How many random numbers should be generated. :returns Random numbers from N(mean, var). """ # generate some samples elements = np.empty(num_samples) for k in range(num_samples): # generate sample x = self.EG.sample() un = self.UG.sample() # reject while un > np.exp(-(x - 1)**2 / 2): x = self.sample() un = self.UG.sample() # accept u = self.UG.sample() elements[k] = (1 - 2 * int(u <= 0.5)) * x return np.sqrt(self.var) * elements + self.mean def c_pdf(self, x): """This method calculates the density N(x|mean, var). :param x What values should be evaluated. :returns The probability this element occurs. """ var = self.var mean = self.mean return 1 / np.sqrt(2 * var * np.pi) * np.exp( -0.5 * (np.subtract(x, mean)**2) / var)