# encoding: utf-8
# ---------------------------------------------------------------------------
# Copyright (C) 2008-2014, IPython Development Team and Enthought, Inc.
# Distributed under the terms of the BSD License. See COPYING.rst.
# ---------------------------------------------------------------------------
"""
Contains the `Random` class that emulates `numpy.random` for `DistArray`.
"""
from __future__ import absolute_import
from distarray.globalapi.distarray import DistArray
from distarray.globalapi.maps import asdistribution
[docs]class Random(object):
def __init__(self, context):
self.context = context
[docs] def seed(self, seed=None):
"""
Seed the random number generators on each engine.
Parameters
----------
seed : None, int, or array of integers
Base random number seed to use on each engine.
If None, then a non-deterministic seed is obtained from the
operating system. Otherwise, the seed is used as passed,
and the sequence of random numbers will be deterministic.
Each individual engine has its state adjusted so that
it is different from each other engine. Thus, each engine
will compute a different sequence of random numbers.
"""
def _local_setup_random(seed, comm):
from numpy import random
from distarray.localapi.random import label_state
random.seed(seed)
label_state(comm)
self.context.apply(_local_setup_random,
(seed, self.context.comm),
targets=self.context.targets)
[docs] def rand(self, shape_or_dist):
"""Random values over a given distribution.
Create a distarray of the given shape and propagate it with
random samples from a uniform distribution
over ``[0, 1)``.
Parameters
----------
shape_or_dist : shape tuple or Distribution object
Returns
-------
out : DistArray
Random values.
"""
return self._local_rand_call('rand', shape_or_dist)
[docs] def normal(self, shape_or_dist, loc=0.0, scale=1.0):
"""Draw random samples from a normal (Gaussian) distribution.
The probability density function of the normal distribution, first
derived by De Moivre and 200 years later by both Gauss and Laplace
independently [2]_, is often called the bell curve because of
its characteristic shape (see the example below).
The normal distributions occurs often in nature. For example, it
describes the commonly occurring distribution of samples influenced
by a large number of tiny, random disturbances, each with its own
unique distribution [2]_.
Parameters
----------
loc : float
Mean ("centre") of the distribution.
scale : float
Standard deviation (spread or "width") of the distribution.
shape_or_dist : shape tuple or Distribution object
Notes
-----
The probability density for the Gaussian distribution is
.. math:: p(x) = \\frac{1}{\\sqrt{ 2 \\pi \\sigma^2 }}
e^{ - \\frac{ (x - \\mu)^2 } {2 \\sigma^2} },
where :math:`\\mu` is the mean and :math:`\\sigma` the standard
deviation. The square of the standard deviation, :math:`\\sigma^2`, is
called the variance.
The function has its peak at the mean, and its "spread" increases with
the standard deviation (the function reaches 0.607 times its maximum at
:math:`x + \\sigma` and :math:`x - \\sigma` [2]_). This implies that
`numpy.random.normal` is more likely to return samples lying close to
the mean, rather than those far away.
References
----------
.. [1] Wikipedia, "Normal distribution",
http://en.wikipedia.org/wiki/Normal_distribution
.. [2] P. R. Peebles Jr., "Central Limit Theorem" in "Probability,
Random Variables and Random Signal Principles", 4th ed., 2001,
pp. 51, 51, 125.
"""
return self._local_rand_call('normal', shape_or_dist,
dict(loc=loc, scale=scale))
[docs] def randint(self, shape_or_dist, low, high=None):
"""Return random integers from `low` (inclusive) to `high` (exclusive).
Return random integers from the "discrete uniform" distribution in the
"half-open" interval [`low`, `high`). If `high` is None (the default),
then results are from [0, `low`).
Parameters
----------
shape_or_dist : shape tuple or Distribution object
low : int
Lowest (signed) integer to be drawn from the distribution (unless
``high=None``, in which case this parameter is the *highest* such
integer).
high : int, optional
if provided, one above the largest (signed) integer to be drawn
from the distribution (see above for behavior if ``high=None``).
Returns
-------
out : DistArray of ints
DistArray of random integers from the appropriate distribution.
"""
return self._local_rand_call('randint', shape_or_dist,
dict(low=low, high=high))
[docs] def randn(self, shape_or_dist):
"""Return samples from the "standard normal" distribution.
Parameters
----------
shape_or_dist : shape tuple or Distribution object
Returns
-------
out : DistArray
A DistArray of floating-point samples from the standard normal
distribution.
"""
return self._local_rand_call('randn', shape_or_dist)
def _local_rand_call(self, local_func_name, shape_or_dist, kwargs=None):
kwargs = kwargs or {}
def _local_call(comm, local_func_name, ddpr, kwargs):
import distarray.localapi.random as local_random
from distarray.localapi.maps import Distribution
local_func = getattr(local_random, local_func_name)
if len(ddpr):
dim_data = ddpr[comm.Get_rank()]
else:
dim_data = ()
dist = Distribution(dim_data=dim_data, comm=comm)
return proxyize(local_func(distribution=dist, **kwargs))
distribution = asdistribution(self.context, shape_or_dist)
ddpr = distribution.get_dim_data_per_rank()
args = (distribution.comm, local_func_name, ddpr, kwargs)
da_key = self.context.apply(_local_call, args,
targets=distribution.targets)
return DistArray.from_localarrays(da_key[0], distribution=distribution)