Skip to content

Random Distributions#

Introduction#

Random number generators can be used at several places:

  • while initializing parameters or variables,
  • while creating connection patterns,
  • when injecting noise into a neural or synaptic variable.

ANNarchy provides several random distribution objects, implementing the following distributions:

  • Uniform
  • DiscreteUniform
  • Normal
  • LogNormal
  • Gamma
  • Exponential

Warning

DiscreteUniform, Gamma and Exponential distributions are not available if the CUDA paradigm is used.

They can be used in the Python code, as a normal object:

dist = Uniform(-1.0, 1.0)
values = dist.get_values(100)

or inside mathematical expressions:

tau * dv/dt + v = g_exc + Normal(0.0, 20.0)
``````

The Python objects rely on the `numpy.random` library, while the C++ values are based on the standard library of C++11.

The seed of the underlying random number generator (Mersenne twister, mt19937 in C++11) can be set globally, by defining its value in `setup()`:

```python
setup(seed=187348768237)

All random distribution objects (Python or C++) will use this seed. By default, the global seed is taken to be time(NULL).

The seed can also be set individually for each RandomDistribution object as a last argument:

dist = Uniform(-1.0, 1.0, 36875937346)

as well as in a mathematical expression:

tau * dv/dt + v = g_exc + Normal(0.0, 20.0, 497536526)

Implementation details#

ANNarchy uses default implementations for random number generation: STL methods of C++11 for OpenMP and the device API of the curand library for CUDA.

As engines, we use mt19937 on openMP side and XORWOW on CUDA. The latter is subject to changes in future releases.

It may be important to know that the drawing mechanisms differ between openMP and CUDA slightly:

  • openMP: all distribution objects draw the numbers from one source in a single thread.
  • CUDA: each distribution object has its own source, the random numbers are drawn in a parallel way.

For further details on random numbers on GPUs please refer to the curand documentation:

http://docs.nvidia.com/cuda/curand/device-api-overview.html#device-api-overview

ANNarchy.core.Random.Uniform #

Bases: RandomDistribution

Random distribution object using the uniform distribution between min and max.

The returned values are floats in the range [min, max].

Source code in ANNarchy/core/Random.py
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
class Uniform(RandomDistribution):
    """
    Random distribution object using the uniform distribution between ``min`` and ``max``.

    The returned values are floats in the range [min, max].
    """
    def __init__(self, min, max):
        """
        :param min: minimum value.
        :param max: maximum value.
        """
        self.min = min
        self.max = max

    def get_values(self, shape):
        """
        Returns a Numpy array with the given shape.
        """
        return np.random.uniform(self.min, self.max, shape)

    def latex(self):
        return "$\\mathcal{U}$(" + str(self.min) + ', ' + str(self.max) + ')'

    def get_cpp_args(self):
        return self.min, self.max

__init__(min, max) #

Parameters:

  • min

    minimum value.

  • max

    maximum value.

Source code in ANNarchy/core/Random.py
71
72
73
74
75
76
77
def __init__(self, min, max):
    """
    :param min: minimum value.
    :param max: maximum value.
    """
    self.min = min
    self.max = max

get_values(shape) #

Returns a Numpy array with the given shape.

Source code in ANNarchy/core/Random.py
79
80
81
82
83
def get_values(self, shape):
    """
    Returns a Numpy array with the given shape.
    """
    return np.random.uniform(self.min, self.max, shape)

ANNarchy.core.Random.DiscreteUniform #

Bases: RandomDistribution

Random distribution object using the discrete uniform distribution between min and max.

The returned values are integers in the range [min, max].

Source code in ANNarchy/core/Random.py
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
class DiscreteUniform(RandomDistribution):
    """
    Random distribution object using the discrete uniform distribution between ``min`` and ``max``.

    The returned values are integers in the range [min, max].
    """
    def __init__(self, min, max):
        """
        :param min: minimum value.
        :param max: maximum value.
        """
        self.min = min
        self.max = max

    def get_values(self, shape):
        """
        Returns a np.ndarray with the given shape.
        """
        # randint draws from half-open interval [min, max)
        return np.random.randint(self.min, self.max+1, shape)

    def latex(self):
        return "$\\mathcal{U}$(" + str(self.min) + ', ' + str(self.max) + ')'

__init__(min, max) #

Parameters:

  • min

    minimum value.

  • max

    maximum value.

Source code in ANNarchy/core/Random.py
 97
 98
 99
100
101
102
103
def __init__(self, min, max):
    """
    :param min: minimum value.
    :param max: maximum value.
    """
    self.min = min
    self.max = max

get_values(shape) #

Returns a np.ndarray with the given shape.

Source code in ANNarchy/core/Random.py
105
106
107
108
109
110
def get_values(self, shape):
    """
    Returns a np.ndarray with the given shape.
    """
    # randint draws from half-open interval [min, max)
    return np.random.randint(self.min, self.max+1, shape)

ANNarchy.core.Random.Normal #

Bases: RandomDistribution

Random distribution instance returning a random value based on a normal (Gaussian) distribution.

Source code in ANNarchy/core/Random.py
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
class Normal(RandomDistribution):
    """
    Random distribution instance returning a random value based on a normal (Gaussian) distribution.
    """
    def __init__(self, mu, sigma, min=None, max=None):
        """
        :param mu: mean of the distribution.
        :param sigma: standard deviation of the distribution.
        :param min: minimum value (default: unlimited).
        :param max: maximum value (default: unlimited).
        """
        if sigma < 0.0:
            Global._error("Normal: the standard deviation sigma should be positive.")
        self.mu = mu
        self.sigma = sigma
        self.min = min
        self.max = max

    def get_values(self, shape):
        """
        Returns a np.ndarray with the given shape
        """
        data = np.random.normal(self.mu, self.sigma, shape)
        if self.min != None:
            data[data<self.min] = self.min
        if self.max != None:
            data[data>self.max] = self.max
        return data

    def latex(self):
        return "$\\mathcal{N}$(" + str(self.mu) + ', ' + str(self.sigma) + ')'

    def get_cpp_args(self):
        return self.mu, self.sigma

__init__(mu, sigma, min=None, max=None) #

Parameters:

  • mu

    mean of the distribution.

  • sigma

    standard deviation of the distribution.

  • min

    minimum value (default: unlimited).

  • max

    maximum value (default: unlimited).

Source code in ANNarchy/core/Random.py
120
121
122
123
124
125
126
127
128
129
130
131
132
def __init__(self, mu, sigma, min=None, max=None):
    """
    :param mu: mean of the distribution.
    :param sigma: standard deviation of the distribution.
    :param min: minimum value (default: unlimited).
    :param max: maximum value (default: unlimited).
    """
    if sigma < 0.0:
        Global._error("Normal: the standard deviation sigma should be positive.")
    self.mu = mu
    self.sigma = sigma
    self.min = min
    self.max = max

get_values(shape) #

Returns a np.ndarray with the given shape

Source code in ANNarchy/core/Random.py
134
135
136
137
138
139
140
141
142
143
def get_values(self, shape):
    """
    Returns a np.ndarray with the given shape
    """
    data = np.random.normal(self.mu, self.sigma, shape)
    if self.min != None:
        data[data<self.min] = self.min
    if self.max != None:
        data[data>self.max] = self.max
    return data

ANNarchy.core.Random.LogNormal #

Bases: RandomDistribution

Random distribution instance returning a random value based on lognormal distribution.

Source code in ANNarchy/core/Random.py
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
class LogNormal(RandomDistribution):
    """
    Random distribution instance returning a random value based on lognormal distribution.
    """
    def __init__(self, mu, sigma, min=None, max=None):
        """
        :param mu: mean of the distribution.
        :param sigma: standard deviation of the distribution.
        :param min: minimum value (default: unlimited).
        :param max: maximum value (default: unlimited).
        """
        if sigma < 0.0:
            Global._error("LogNormal: the standard deviation sigma should be positive.")
        self.mu = mu
        self.sigma = sigma
        self.min = min
        self.max = max

    def get_values(self, shape):
        """
        Returns a np.ndarray with the given shape
        """
        data = np.random.lognormal(self.mu, self.sigma, shape)
        if self.min != None:
            data[data<self.min] = self.min
        if self.max != None:
            data[data>self.max] = self.max
        return data

    def latex(self):
        return "$\\ln\\mathcal{N}$(" + str(self.mu) + ', ' + str(self.sigma) + ')'

    def get_cpp_args(self):
        return self.mu, self.sigma

__init__(mu, sigma, min=None, max=None) #

Parameters:

  • mu

    mean of the distribution.

  • sigma

    standard deviation of the distribution.

  • min

    minimum value (default: unlimited).

  • max

    maximum value (default: unlimited).

Source code in ANNarchy/core/Random.py
155
156
157
158
159
160
161
162
163
164
165
166
167
def __init__(self, mu, sigma, min=None, max=None):
    """
    :param mu: mean of the distribution.
    :param sigma: standard deviation of the distribution.
    :param min: minimum value (default: unlimited).
    :param max: maximum value (default: unlimited).
    """
    if sigma < 0.0:
        Global._error("LogNormal: the standard deviation sigma should be positive.")
    self.mu = mu
    self.sigma = sigma
    self.min = min
    self.max = max

get_values(shape) #

Returns a np.ndarray with the given shape

Source code in ANNarchy/core/Random.py
169
170
171
172
173
174
175
176
177
178
def get_values(self, shape):
    """
    Returns a np.ndarray with the given shape
    """
    data = np.random.lognormal(self.mu, self.sigma, shape)
    if self.min != None:
        data[data<self.min] = self.min
    if self.max != None:
        data[data>self.max] = self.max
    return data

ANNarchy.core.Random.Gamma #

Bases: RandomDistribution

Random distribution instance returning a random value based on gamma distribution.

Source code in ANNarchy/core/Random.py
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
class Gamma(RandomDistribution):
    """
    Random distribution instance returning a random value based on gamma distribution.
    """
    def __init__(self, alpha, beta=1.0, seed=-1, min=None, max=None):
        """
        :param alpha: shape of the gamma distribution
        :param beta: scale of the gamma distribution
        :param min: minimum value returned (default: unlimited).
        :param max: maximum value returned (default: unlimited).
        """
        self.alpha = alpha
        self.beta = beta
        self.min = min
        self.max = max

    def get_values(self, shape):
        """
        Returns a np.ndarray with the given shape
        """
        data = np.random.gamma(self.alpha, self.beta, shape)
        if self.min != None:
            data[data<self.min] = self.min
        if self.max != None:
            data[data>self.max] = self.max
        return data

    def latex(self):
        return "$\\Gamma$(" + str(self.alpha) + ', ' + str(self.beta) + ')'

__init__(alpha, beta=1.0, seed=-1, min=None, max=None) #

Parameters:

  • alpha

    shape of the gamma distribution

  • beta

    scale of the gamma distribution

  • min

    minimum value returned (default: unlimited).

  • max

    maximum value returned (default: unlimited).

Source code in ANNarchy/core/Random.py
226
227
228
229
230
231
232
233
234
235
236
def __init__(self, alpha, beta=1.0, seed=-1, min=None, max=None):
    """
    :param alpha: shape of the gamma distribution
    :param beta: scale of the gamma distribution
    :param min: minimum value returned (default: unlimited).
    :param max: maximum value returned (default: unlimited).
    """
    self.alpha = alpha
    self.beta = beta
    self.min = min
    self.max = max

get_values(shape) #

Returns a np.ndarray with the given shape

Source code in ANNarchy/core/Random.py
238
239
240
241
242
243
244
245
246
247
def get_values(self, shape):
    """
    Returns a np.ndarray with the given shape
    """
    data = np.random.gamma(self.alpha, self.beta, shape)
    if self.min != None:
        data[data<self.min] = self.min
    if self.max != None:
        data[data>self.max] = self.max
    return data

ANNarchy.core.Random.Exponential #

Bases: RandomDistribution

Random distribution instance returning a random value based on exponential distribution, according the density function:

\[P(x | \lambda) = \lambda e^{(-\lambda x )}\]
Source code in ANNarchy/core/Random.py
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
class Exponential(RandomDistribution):
    """
    Random distribution instance returning a random value based on exponential distribution, according the density function:

    $$P(x | \\lambda) = \\lambda e^{(-\\lambda x )}$$

    """
    def __init__(self, Lambda, min=None, max=None):
        """
        **Note:** ``Lambda`` is capitalized, otherwise it would be a reserved Python keyword.

        :param Lambda: rate parameter.
        :param min: minimum value (default: unlimited).
        :param max: maximum value (default: unlimited).

        """
        if Lambda < 0.0:
            Global._error("Exponential: the rate parameter Lambda should be positive.")
        self.Lambda = Lambda
        self.min = min
        self.max = max

    def get_values(self, shape):
        """
        Returns a np.ndarray with the given shape.
        """
        data = np.random.exponential(self.Lambda, shape)
        if self.min != None:
            data[data<self.min] = self.min
        if self.max != None:
            data[data>self.max] = self.max
        return data

    def latex(self):
        return "$\\exp$(" + str(self.Lambda) + ')'

__init__(Lambda, min=None, max=None) #

Note: Lambda is capitalized, otherwise it would be a reserved Python keyword.

Parameters:

  • Lambda

    rate parameter.

  • min

    minimum value (default: unlimited).

  • max

    maximum value (default: unlimited).

Source code in ANNarchy/core/Random.py
193
194
195
196
197
198
199
200
201
202
203
204
205
206
def __init__(self, Lambda, min=None, max=None):
    """
    **Note:** ``Lambda`` is capitalized, otherwise it would be a reserved Python keyword.

    :param Lambda: rate parameter.
    :param min: minimum value (default: unlimited).
    :param max: maximum value (default: unlimited).

    """
    if Lambda < 0.0:
        Global._error("Exponential: the rate parameter Lambda should be positive.")
    self.Lambda = Lambda
    self.min = min
    self.max = max

get_values(shape) #

Returns a np.ndarray with the given shape.

Source code in ANNarchy/core/Random.py
208
209
210
211
212
213
214
215
216
217
def get_values(self, shape):
    """
    Returns a np.ndarray with the given shape.
    """
    data = np.random.exponential(self.Lambda, shape)
    if self.min != None:
        data[data<self.min] = self.min
    if self.max != None:
        data[data>self.max] = self.max
    return data