"""
parameters.random
=================
A set of classes representing statistical distributions, with an interface that
is compatible with the ParameterSpace class in the parameters module.
Classes
-------
GammaDist - gamma.pdf(x,a,b) = x**(a-1)*exp(-x/b)/gamma(a)/b**a
NormalDist - normal distribution
UniformDist - uniform distribution
"""
from __future__ import absolute_import
try:
import numpy
import numpy.random
have_numpy = True
except ImportError:
have_numpy = False
try:
import scipy.stats
have_scipy = True
except ImportError:
have_scipy = False
import math
[docs]class ParameterDist(object):
"""
missing docstring
"""
def __init__(self, **params):
self.params = params
self.dist_name = 'ParameterDist'
def __repr__(self):
if len(self.params) == 0:
return '%s()' % (self.dist_name,)
s = '%s(' % (self.dist_name,)
for key in self.params:
s += '%s=%s,' % (key, str(self.params[key]))
return s[:-1]+')'
[docs] def next(self, n=1):
raise NotImplementedError(
'This is an abstract base class and cannot be used directly')
[docs] def from_stats(self, vals, bias=0.0, expand=1.0):
"""missing docstring"""
if have_numpy:
self.__init__(mean=numpy.mean(vals)+bias,
std=numpy.std(vals)*expand)
else:
raise Exception("Error: numpy was not found at import time.")
def __eq__(self, o):
# should we track the state of the rng and return False if it is
# different between self and o?
if (type(self) == type(o) and
self.dist_name == o.dist_name and
self.params == o.params):
return True
else:
return False
[docs]class GammaDist(ParameterDist):
"""
gamma.pdf(x,a,b) = x**(a-1)*exp(-x/b)/gamma(a)/b**a
Yields strictly positive numbers.
Generally the distribution is implemented by `scipy.stats.gamma.pdf(x/b,a)/b`
For more info, in ipython type::
>>> ? scipy.stats.gamma
"""
def __init__(self, mean=None, std=None, repr_mode='ms', **params):
"""
repr_mode specifies how the dist is displayed,
either mean,var ('ms', the default) or a,b ('ab')
"""
self.repr_mode = repr_mode
if 'm' in params and mean is None:
mean = params['m']
if 's' in params and std is None:
std = params['s']
# neither mean nor std specified
if (mean, std) == (None, None):
if 'a' in params:
a = params['a']
else:
a = 1.0
if 'b' in params:
b = params['b']
else:
b = 1.0
else:
if mean is None:
mean = 0.0
if std is None:
std = 1.0
a = mean**2/std**2
b = mean/a
ParameterDist.__init__(self, a=a, b=b)
self.dist_name = 'GammaDist'
if have_scipy:
def next(self, n=1):
return scipy.stats.gamma.rvs(self.params['a'], size=n)*self.params['b']
else:
def next(self, n=1):
raise Exception(
'Error: scipy was not found at import time. GammaDist realization disabled.')
def mean(self):
return self.params['a']*self.params['b']
def std(self):
return self.params['b']*math.sqrt(self.params['a'])
def __repr__(self):
if self.repr_mode == 'ms':
return '%s(m=%f,s=%f)' % (self.dist_name, self.mean(), self.std())
else:
return '%s(a=%f,b=%f)' % (self.dist_name, self.params['a'], self.params['b'])
[docs]class NormalDist(ParameterDist):
"""
normal distribution with parameters
mean + std
"""
def __init__(self, mean=0.0, std=1.0):
ParameterDist.__init__(self, mean=mean, std=std)
self.dist_name = 'NormalDist'
if have_numpy:
def next(self, n=1):
return numpy.random.normal(loc=self.params['mean'], scale=self.params['std'], size=n)
else:
def next(self, n=1):
raise Exception(
'Error: numpy was not found at import time. NormalDist realization disabled.')