Generates pseudorandom numbers from a general discrete distribution using an alias method or optionally a table lookup method.
#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.
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 routine 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.)
An integer array of length n_random containing the random discrete deviates. To release this space, use free.
#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)
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 for
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 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.
Routine 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 routine 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.
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 <stdio.h>
#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);
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);
}
Random deviates
3 2 2 3 5
Random deviates
1 3 4 5 3
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 <stdio.h>
#include <imsls.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);
}
Binomial (20, 0.5) random deviates
14 9 12 10 12
Visual Numerics, Inc. PHONE: 713.784.3131 FAX:713.781.9260 |