CNL Stat : Random Number Generation : random_general_discrete
random_general_discrete
Generates pseudorandom numbers from a general discrete distribution using an alias method or optionally a table lookup method.
Synopsis
#include <imsls.h>
int *imsls_f_random_general_discrete (int n_random, int imin, int nmass, float probs[], 0)
The type double function is imsls_d_random_general_discrete.
Required Arguments
int n_random (Input)
Number of random numbers to generate.
int imin (Input)
Smallest value the random deviate can assume.
This is the value corresponding to the probability in probs[0].
int nmass (Input)
Number of mass points in the discrete distribution.
float probs[] (Input)
Array of length nmass containing probabilities associated with the individual mass points. The elements of probs must be nonnegative and must sum to 1.0.
If the optional argument IMSLS_TABLE is used, then probs is a vector of length at least nmass + 1 containing in the first nmass positions the cumulative probabilities and, possibly, indexes to speed access to the probabilities. IMSL function imsls_f_discrete_table_setup can be used to initialize probs properly. If no elements of probs are used as indexes, probs [nmass] is 0.0 on input. The value in probs[0] is the probability of imin. The value in probs [nmass-1] must be exactly 1.0 (since this is the CDF at the upper range of the distribution.)
Return Value
An integer array of length n_random containing the random discrete deviates. To release this space, use imsls_free.
Synopsis with Optional Arguments
#include <imsls.h>
int *imsls_f_random_general_discrete (int n_random, int imin, int nmass, float probs[],
IMSLS_GET_INDEX_VECTORS, int **iwk, float **wk,
IMSLS_GET_INDEX_VECTORS_USER, int iwk[], float wk[],
IMSLS_SET_INDEX_VECTORS, int iwk[], float wk[],
IMSLS_RETURN_USER, int ir[],
IMSLS_TABLE,
0)
Optional Arguments
IMSLS_GET_INDEX_VECTORS, int **iwk, float **wk (Output)
Retrieve indexing vectors that can be used to increase efficiency when multiple calls will be made to imsls_f_random_general_discrete with the same values in probs.
IMSLS_GET_INDEX_VECTORS_USER, int iwk[], float wk[] (Output)
User-supplied arrays of length nmass used to retrieve indexing vectors that can be used to increase efficiency when multiple calls will be made to imsls_f_random_general_discrete with the same values in probs.
IMSLS_SET_INDEX_VECTORS, int *iwk, float *wk (Input)
Arrays of length nmass that can be used to increase efficiency when multiple calls will be made to imsls_f_random_general_discrete with the same values in probs. These arrays are obtained by using one of the options IMSLS_GET_INDEX_VECTORS or IMSLS_GET_INDEX_VECTORS_USER in the first call to imsls_f_random_general_discrete.
IMSLS_TABLE, (Input)
Generate pseudorandom numbers from a general discrete distribution using a table lookup method. If this option is used, then probs is a vector of length at least nmass + 1 containing in the first nmass positions the cumulative probabilities and, possibly, indexes to speed access to the probabilities.
IMSLS_RETURN_USER, int ir[] (Output)
User-supplied array of length n_random containing the random discrete deviates.
Description
Function imsls_f_random_general_discrete generates pseudorandom numbers from a discrete distribution with probability function given in the vector probs; that is
Pr(X = i) = pj
for i = imin, imin + 1, …, imin + nm - 1 where j = i - imin + 1, pj = probs[j-1], imin = imin, and nm = nmass.
The algorithm is the alias method, due to Walker (1974), with modifications suggested by Kronmal and Peterson (1979). The method involves a setup phase, in which the vectors iwk and wk are filled. After the vectors are filled, the generation phase is very fast. To increase efficiency, the first call to imsls_f_random_general_discrete can retrieve the arrays iwk and wk using the optional arguments IMSLS_GET_INDEX_VECTORS or IMSLS_GET_INDEX_VECTORS_USER , then subsequent calls can be made using the optional argument IMSLS_SET_INDEX_VECTORS.
If the optional argument IMSLS_TABLE is used, imsls_f_random_general_discrete generates pseudorandom deviates from a discrete distribution, using the table probs, which contains the cumulative probabilities of the distribution and, possibly, indexes to speed the search of the table. The function imsls_f_discrete_table_setup can be used to set up the table probs. imsls_f_random_general_discrete uses the inverse CDF method to generate the variates.
Examples
Example 1
In this example, imsls_f_random_general_discrete is used to generate five pseudorandom variates from the discrete distribution:
Pr(X = 1) = .05
Pr(X = 2) = .45
Pr(X = 3) = .31
Pr(X = 4) = .04
Pr(X = 5) = .15
When imsls_f_random_general_discrete is called the first time, IMSLS_GET_INDEX_VECTORS is used to initialize the index vectors iwk and wk. In the next call, IMSLS_GET_INDEX_VECTORS is used, so the setup phase is bypassed.
 
#include <imsls.h>
 
int main()
{
int nr = 5, nmass = 5, iopt = 0, imin = 1, *iwk, *ir;
float probs[] = {.05, .45, .31, .04, .15};
float *wk;
 
imsls_random_seed_set(123457);
 
ir = imsls_f_random_general_discrete(nr, imin, nmass, probs,
IMSLS_GET_INDEX_VECTORS, &iwk, &wk,
0);
 
imsls_i_write_matrix("Random deviates", 1, 5, ir,
IMSLS_NO_COL_LABELS,
0);
 
imsls_free(ir);
 
ir = imsls_f_random_general_discrete(nr, imin, nmass, probs,
IMSLS_SET_INDEX_VECTORS, iwk, wk,
0);
 
imsls_i_write_matrix("Random deviates", 1, 5, ir,
IMSLS_NO_COL_LABELS,
0);
}
Output
 
Random deviates
3 2 2 3 5
 
Random deviates
1 3 4 5 3
 
Example 2
In this example, imsls_f_discrete_table_setup is used to set up a table and then imsls_f_random_general_discrete is used to generate five pseudorandom variates from the binomial distribution with parameters 20 and 0.5.
 
#include <imsls.h>
#include <stdlib.h>
 
float prf(int ix);
 
int main()
{
int nndx = 12, imin = 0, nmass = 21, nr = 5;
float del = 0.00001, *cumpr;
 
int *ir = NULL;
 
cumpr = imsls_f_discrete_table_setup (prf, del, nndx, &imin,
&nmass,
0);
 
imsls_random_seed_set(123457);
 
ir = imsls_f_random_general_discrete(nr, imin, nmass, cumpr,
IMSLS_TABLE,
0);
 
imsls_i_write_matrix("Binomial (20, 0.5) random deviates", 1, 5, ir,
IMSLS_NO_COL_LABELS,
0);
}
 
float prf(int ix)
{
int n = 20;
float p = .5;
 
return imsls_f_binomial_pdf (ix, n, p);
}
Output
 
Binomial (20, 0.5) random deviates
14 9 12 10 12