def SetMultinormalInitialPoints(self, mean, var=None): """Generate Initial Points from Multivariate Normal. input:: - mean must be a sequence of length self.nDim - var can be... None: -> it becomes the identity scalar: -> var becomes scalar * I matrix: -> the variance matrix. must be the right size! """ from mystic.tools import random_state rng = random_state(module='numpy.random') assert (len(mean) == self.nDim) if var is None: var = numpy.eye(self.nDim) else: try: # scalar ? float(var) except: # nope. var better be matrix of the right size (no check) pass else: var = var * numpy.eye(self.nDim) for i in range(len(self.population)): self.population[i] = rng.multivariate_normal(mean, var).tolist() return
def SetMultinormalInitialPoints(self, mean, var = None): """Generate Initial Points from Multivariate Normal. input:: - mean must be a sequence of length self.nDim - var can be... None: -> it becomes the identity scalar: -> var becomes scalar * I matrix: -> the variance matrix. must be the right size! """ from mystic.tools import random_state prng = random_state(module='numpy.random') assert(len(mean) == self.nDim) if var is None: var = numpy.eye(self.nDim) else: try: # scalar ? float(var) except: # nope. var better be matrix of the right size (no check) pass else: var = var * numpy.eye(self.nDim) for i in range(len(self.population)): self.population[i] = prng.multivariate_normal(mean, var).tolist() return
def randomly_bin(N, ndim=None, ones=True, exact=True): """ generate N bins randomly gridded across ndim dimensions Inputs: N -- integer number of bins, where N = prod(bins) ndim -- integer length of bins, thus ndim = len(bins) ones -- if False, prevent bins from containing "1s", wherever possible exact -- if False, find N-1 bins for prime numbers """ if ndim == 0: return [] if N == 0: return [0] if ndim else [0] * ndim from itertools import chain from mystic.tools import random_state try: xrange except NameError: xrange = range random = random_state().random def factors(n): result = list() for i in chain([2], xrange(3, n + 1, 2)): s = 0 while n % i == 0: n //= i s += 1 result.extend([i] * s) if n == 1: return result result = factors(N) dim = nfact = len(result) prime = nfact == 1 if ndim: result += [1] * (ndim - (nfact // ndim)) dim = ndim elif ones: result += [1] # add some 'randomness' by adding a "1" # if ones, mix in the 1s; otherwise, only use 1s when ndim < len(result) if ones: result = sorted(result, key=lambda v: random()) else: result[:nfact] = sorted(result[:nfact], key=lambda v: random()) from numpy import product result = [product(result[i::dim]) for i in range(dim)] # if not ones, now needs a full sort to sort in the 1s if not ones: result = sorted(result, key=lambda v: random()) elif not ndim and 1 in result: result.remove(1) # remove the added "1" # if it's a prime, then do N-1 if exact=False if not exact and N > 3 and prime: result = randomly_bin(N - 1, ndim, ones) return result
def _random_samples(lb,ub,npts=10000): """ generate npts random samples between given lb & ub Inputs: lower bounds -- a list of the lower bounds upper bounds -- a list of the upper bounds npts -- number of sample points [default = 10000] """ from mystic.tools import random_state dim = len(lb) pts = random_state(module='numpy.random').rand(dim,npts) for i in range(dim): pts[i] = (pts[i] * abs(ub[i] - lb[i])) + lb[i] return pts #XXX: returns a numpy.array
def _random_samples(lb, ub, npts=10000): """ generate npts random samples between given lb & ub Inputs: lower bounds -- a list of the lower bounds upper bounds -- a list of the upper bounds npts -- number of sample points [default = 10000] """ from mystic.tools import random_state dim = len(lb) pts = random_state(module='numpy.random').rand(dim, npts) for i in range(dim): pts[i] = (pts[i] * abs(ub[i] - lb[i])) + lb[i] return pts #XXX: returns a numpy.array
def randomly_bin(N, ndim=None, ones=True, exact=True): """ generate N bins randomly gridded across ndim dimensions Inputs: N -- integer number of bins, where N = prod(bins) ndim -- integer length of bins, thus ndim = len(bins) ones -- if False, prevent bins from containing "1s", wherever possible exact -- if False, find N-1 bins for prime numbers """ if ndim == 0: return [] if N == 0: return [0] if ndim else [0]*ndim from itertools import chain from mystic.tools import random_state try: xrange except NameError: xrange = range random = random_state().random def factors(n): result = list() for i in chain([2],xrange(3,n+1,2)): s = 0 while n%i == 0: n //= i s += 1 result.extend([i]*s) if n == 1: return result result = factors(N) dim = nfact = len(result) prime = nfact == 1 if ndim: result += [1] * (ndim - (nfact // ndim)); dim = ndim elif ones: result += [1] # add some 'randomness' by adding a "1" # if ones, mix in the 1s; otherwise, only use 1s when ndim < len(result) if ones: result = sorted(result, key=lambda v: random()) else: result[:nfact] = sorted(result[:nfact], key=lambda v: random()) from numpy import product result = [product(result[i::dim]) for i in range(dim)] # if not ones, now needs a full sort to sort in the 1s if not ones: result = sorted(result, key=lambda v: random()) elif not ndim and 1 in result: result.remove(1) # remove the added "1" # if it's a prime, then do N-1 if exact=False if not exact and N > 3 and prime: result = randomly_bin(N-1, ndim, ones) return result
def weighted_select(samples, weights, mass=1.0): """randomly select a sample from weighted set of samples Inputs: samples -- a list of sample points weights -- a list of sample weights mass -- sum of normalized weights """ from numpy import sum, array from mystic.tools import random_state rand = random_state().random # generate a list representing the weighted distribution wts = normalize(weights, mass) wts = array([sum(wts[:i + 1]) for i in range(len(wts))]) # correct for any rounding error wts[-1] = mass # generate a random weight w = mass * rand() # select samples that corresponds to randomly selected weight selected = len(wts[wts <= w]) return samples[selected]
def weighted_select(samples, weights, mass=1.0): """randomly select a sample from weighted set of samples Inputs: samples -- a list of sample points weights -- a list of sample weights mass -- sum of normalized weights """ from numpy import sum, array from mystic.tools import random_state rand = random_state().random # generate a list representing the weighted distribution wts = normalize(weights, mass) wts = array([sum(wts[:i+1]) for i in range(len(wts))]) # correct for any rounding error wts[-1] = mass # generate a random weight w = mass * rand() # select samples that corresponds to randomly selected weight selected = len(wts[ wts <= w ]) return samples[selected]
def __init__(self, generator=None, *args, **kwds): """ generate a sampling distribution with interface dist(size=None) input:: - generator: a 'distribution' method from scipy.stats or numpy.random - args: positional arguments for the distribtution object - kwds: keyword arguments for the distribution object note:: this method only accepts numpy.random methods with the keyword 'size' """ from mystic.tools import random_state rng = random_state(module='numpy.random') if generator is None: generator = rng.random if getattr(generator, 'rvs', False): d = generator(*args, **kwds) self.rvs = lambda size=None: d.rvs(size=size, random_state=rng) else: d = getattr(rng, generator.__name__) self.rvs = lambda size=None: d(size=size, *args, **kwds) return
def scem(Ck, ak, Sk, Sak, target, cn): """ This is the SCEM algorithm starting from line [35] of the reference [1]. - [inout] Ck is the kth 'complex' with m points. This should be an m by n array n being the dimensionality of the density function. i.e., the data are arranged in rows. Ck is assumed to be sorted according to the target density. - [inout] ak, the density of the points of Ck. - [inout] Sk, the entire chain. (should be a list) - [inout] Sak, the cost of the entire chain (should be a list) Sak would be more convenient to use if it is a numpy array, but we need to append to it frequently. - [in] target: target density function - [in] cn: jumprate. (see Paragraph 37 of [1.] - The invariants: ak is always aligned with Ck, and are the cost of Ck - Similarly, Sak is always aligned with Sk in the same way. - On return... sort order in Ck/ak is destroyed. but see sort_complex2 """ import numpy from mystic.tools import random_state prng = random_state(module=numpy.random) # function level constants T = 100000. # predefined likelihood ratio. Paragraph 45 of [1.] # Sort Ck according to ak #Ck, ak = sort_complex0(Ck, ak) #print("ak before: %s" % ak) #Ck, ak = sort_complex(Ck, ak) sort_complex2(Ck, ak) #print("ak after: %s" % ak) # number of points per complex M = Ck.shape[0] mu = numpy.mean(Ck,0) # row mean # (numpy.cov takes data in columns) Sigma = numpy.cov(numpy.transpose(Ck)) # Gamma (line 35 of [1]. Best to Worst) Gamma = ak[0] / (ak[-1]+TINY) if len(Sak) >= M: meansak = numpy.mean(Sak[-M:]) else: meansak = numpy.mean(Sak) alpha_k = numpy.mean(ak) / (meansak+TINY) if alpha_k < T: # Paragraph 37 of [1] basept = Sk[-1] else: # numpy.mean(asak) is very close to zero. # Paragraph 38 of [1] basept = mu # TODO should take a proposal instead ! Yt = prng.multivariate_normal(basept, cn*cn * Sigma) cY = target(Yt) # print("new/orig : %s %s" % (cY, Sak[-1])) r = min( cY / (Sak[-1]+TINY), 1) if prng.rand() <= r: Sk.append(Yt) Sak.append(cY) # Paragraph 43 of [1] (update the best of Ck) Ck[0], ak[0] = Sk[-1], Sak[-1] else: Sk.append(Sk[-1]) Sak.append(Sak[-1]) if Gamma > T and Sak[-1] > ak[-1]: # Paragraph 43 of [1] (update the worst of Ck) Ck[-1], ak[-1] = Sk[-1], Sak[-1] # mainly because of the logic in Paragraph [43] that updates the complex, # this function is not "functional" and modifies its argument instead. # hence no return value return