SRFI 194

Random Data Generators

  1. SRFI 194
  2. Description
  3. Authors
  4. Repository
  5. Requirements
  6. API
    1. Current Random Source
    2. Uniform distributions
  7. Nonuniform distributions
    1. Generator Operations
  8. Future Directions
  9. Examples
    1. Generate a list of integers
    2. Generate signed 8 bit integers
    3. Generate random reals
    4. Generate random booleans
    5. Generate random characters from a string
    6. Draw numbers from the normal distribution
  10. License
  11. Version History

Description

A Chicken port of the reference implementation of SRFI 194. Whenever possible, this library uses implementations from Chicken's srfi-27 egg.

Authors

SRFI 194 authors: Shiro Kawai (design), Arvydas Silanskas (implementation), Linas Vepštas (implementation), and John Cowan (editor and shepherd)

Chicken maintainer: Peter McGoron

Repository

https://software.mcgoron.com/peter/srfi-194-egg

Requirements

API

The following is mostly copy-pasted from the SRFI, with some Chicken-specific notes.

Current Random Source

[procedure] (current-random-source)

An r7rs or SRFI 39 parameter that provides the random source for all the procedures in this SRFI. Its initial value is default-random-source from srfi-27. Use parameterize to specify a dynamic scope in which a different srfi-27 random source is used when creating new generators. The behavior of existing generators is not affected by changes to this parameter.

Chicken note: This is the same parameter as the one exported from the srfi-27 egg.

[procedure] (with-random-source random-source thunk)

Binds current-random-source to random-source and then invokes thunk.

[procedure] (make-random-source-generator i)

Returns a generator of random sources. Each invocation of the generator returns a new random source created by calling make-random-source (srfi-27). The new random source is passed to random-source-pseudo-randomize! with i, and successive integers j (starting with 0), before being returned.

The random sources are guaranteed to be distinct as long as i and j are not too large and the generator is not called too many times. What counts as "too large/many" depends on the SRFI 27 implementation; the sample implementation works correctly if i < 2^63 and j < 2^51 and no more than 2^76 values are generated.

Uniform distributions

These generators generate uniformly distributed values of various simple Scheme types.

[procedure] (make-random-integer-generator lower-bound upper-bound)

Returns a generator of exact integers between lower-bound (inclusive) and upper-bound (exclusive) uniformly. It is an error if the bounds are not exact integers or if the specified interval is empty.

Chicken note: this is implemented using make-uniform-random-integers from srfi-27. Note that make-uniform-random-integers takes two inclusive bounds, which is different from this interface.

[procedure] (make-random-u1-generator)
[procedure] (make-random-u8-generator)
[procedure] (make-random-s8-generator)
[procedure] (make-random-u16-generator)
[procedure] (make-random-s16-generator)
[procedure] (make-random-u32-generator)
[procedure] (make-random-s32-generator)
[procedure] (make-random-u64-generator)
[procedure] (make-random-s64-generator)

These procedures return generators of exact integers in the ranges of 1-bit unsigned and 8, 16, 32, and 64-bit signed and unsigned values respectively. These values can be stored in the corresponding homogeneous vectors of srfi-160 and srfi-178.

[procedure] (clamp-real-number lower-bound upper-bound value)

Returns value clamped to be between lower-bound and upper-bound, inclusive. Note that this procedure works with either exact or inexact numbers, but will produce strange results with a mixture of the two. It is an error if the specified interval is empty.

[procedure] (make-random-real-generator lower-bound upper-bound)

Returns a generator that generates inexact real numbers uniformly. (Note that this is not the same as returning all possible IEEE floats within the stated range uniformly.) The procedure returns reals between lower-bound and upper-bound, both inclusive. The similar procedure random-real in SRFI 27 uses the exclusive bounds 0.0 and 1.0. It is an error if the specified interval is empty.

[procedure] (make-random-rectangular-generator real-lower-bound real-upper-bound imaginary-lower-bound imag-upper-bound)

Returns a generator that generates inexact complex numbers uniformly. The procedure returns complex numbers in a rectangle whose real part is between real-lower-bound and real-upper-bound (both inclusive), and whose imaginary part is between imag-lower-bound and imag-upper-bound (both inclusive). It is an error if either of the specified intervals is empty.

[procedure] (make-random-polar-generator [ origin ] magnitude-lower-bound magnitude-upper-bound [ angle-lower-bound angle-upper-bound ])

Returns a generator that generates inexact complex numbers uniformly. The procedure returns complex numbers in a sector of an annulus whose origin point is origin, whose magnitude is between magnitude-lower-bound and magnitude-upper-bound (both inclusive), and whose angle is between angle-lower-bound and angle-upper-bound (both inclusive). It is an error if either of the specified intervals is empty. The default value of origin is 0+0i, the default value of angle-lower-bound is 0, and the default value of angle-upper-bound is . If all three are defaulted, the resulting shape is a disk centered on the origin.

[procedure] (make-random-boolean-generator)

Generates boolean values (#f and #t) with equal probability.

Chicken note: This is implemented using make-random-bernoullis from srfi-27.

[procedure] (make-random-char-generator string)

Returns a generator that generates characters in string uniformly. Note that the characters in string need not be distinct, which allows simple weighting. It is an error if string is empty.

[procedure] (make-random-string-generator k string)

Returns a generator that generates random strings whose characters are in string. Note that the characters in string need not be distinct, which allows simple weighting. The length of the strings is uniformly distributed between 0 (inclusive) and the length of string (exclusive). It is an error if string is empty.

Nonuniform distributions

[procedure] (make-bernoulli-generator p)

Returns a generator that yields 1 with probability p and 0 with probability 1 - p.

Chicken note: This is implemented in terms of make-random-bernoullis from srfi-27, except that make-random-bernoullis returns booleans, not integers.

[procedure] (make-binomial-generator n p)

Returns a binomial random variate generator, which conceptually is the sum of n Bernoulli-p random variables.

Chicken note: This is implemented in terms of make-random-binomials from srfi-27.

[procedure] (make-categorical-generator weight-vec)

Returns a generator that yields an exact integer n between 0 (inclusive) and the length of weight-vec (inclusive) with probability equal to the nth element of weight-vec divided by the sum of its elements. It is an error if any element of weight-vec is negative or their sum is zero.

[procedure] (make-normal-generator [ mean [ deviation ] ])

Returns a generator that yields real numbers from a normal distribution with the specified mean and deviation. The default value of mean is 0.0 and deviation is 1.0.

Chicken note: This is implemented in terms of make-random-normals from srfi-27.

[procedure] (make-exponential-generator mean)

Returns a generator that yields real numbers from an exponential distribution with the specified mean.

Chicken note: Unlike make-random-exponentials from srfi-27, this procedure does not limit mean to be less than or equal to 1.

[procedure] (make-geometric-generator p)

Returns a generator that yields integers from the geometric distribution with success probability p (0 <= p <= 1). The mean is 1/p and variance is (1-p)/p^2.

[procedure] (make-poisson-generator L)

Returns a generator that yields integers from the Poisson distribution with mean L, variance L.

Chicken note: This is implemented in terms of make-random-poissons from srfi-27.

[procedure] (make-zipf-generator N [ s [ q ] ])

Returns a generator that yields exact integers k from the generalized Zipf distribution 1/(k+q^s) such that 1 ≤ k ≤ N). The default value of s is 1.0 and the default value of q is 0.0. Parameters outside the following ranges are likely to result in overflows or loss of precision: -10 < s < 100, -0.5 < q < 2^8, and 1 ≤ N.

The following three procedures generate points of real k-dimensional Euclidean space. These points are modeled as Scheme vectors of real numbers of length k.

[procedure] (make-sphere-generator n)

Returns a generator that generates points in real (n + 1)-dimensional Euclidean space that are randomly, independently distributed on the surface of an n-sphere. That is, the vectors are of unit length.

[procedure] (make-ellipsoid-generator axes)
   Returns a generator that generates points in real {{(n + 1)}}-dimensional Euclidean space that are randomly, independently distributed on the surface of an {{n}}-ellipsoid. The ellipsoid is specified by the axes argument, which must be a vector of real numbers giving the lengths of the axes. Given axes = {{(a, b, ...)}}, then the generated vectors {{v=(x, y, ...)}} obey {{1 = x2/a2 + y2/b2 + ... .}}
[procedure] (make-ball-generator dimensions)

Returns a generator that generates points in real n-dimensional Euclidean space corresponding to the inside of an n-ball. The dimensions argument can be either a vector of n real numbers, in which case they are taken as the axes of an ellipsoid, or it can be an integer, in which case it's treated as the dimension n, (i.e. the generated vectors are inside a ball of radius 1.)

Generator Operations

[procedure] (gsampling generator ...)

Takes the generators and returns a new generator. Every time the resulting generator is called, it picks one of the input generators with equal probability, then calls it to get a value. When all the generators are exhausted or no generators are specified, the new generator returns an end-of-file object.

Future Directions

Currently the generators use Scheme's generic math procedures. Restricting everything to floats might make things faster.

Examples

In the following examples, we use the generator->list procedure (from srfi-158) to show some concrete data from the generators.

(import (srfi 194) (srfi 158))

Generate a list of integers

;; A die roller
(define die (make-random-integer-generator 1 7))

;; Roll the die 10 times
(generator->list die 10) ; ⇒ (6 6 2 4 2 5 5 1 2 2)

Generate signed 8 bit integers

(generator->list (make-random-s8-generator) 10) ;⇒ (20 -101 50 -99 -111 -28 -19 -61 39 110)

Generate random reals

(define uniform-100 (make-random-real-generator 0 100))

(generator->list uniform-100 3) ;⇒ (81.67965004942268 81.84927577572596 53.02443813660833)

(define generate-from-0-below-1
  (gfilter (lambda (r) (not (= r 1.0))) (make-random-real-generator 0.0 1.0)))
(generator->list generate-from-0-below-1 10) ; -> (0.474825107670301 0.822675192755749 0.0136297582264499 0.675879765670512 0.835390610797621 0.751728161787488 0.399774461321786 0.210700704442744 0.603465786092189 0.164001777794298)

Generate random booleans

(generator->list (make-random-boolean-generator) 10) ;⇒ (#f #f #t #f #f #t #f #f #f #f)

Generate random characters from a string

(define alphanumerics "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789")
(define alphanumeric-chars (make-random-char-generator alphanumerics))

(generator->list alphanumeric-chars 10) ;⇒ (#\f #\m #\3 #\S #\z #\m #\x #\S #\l #\y)

Draw numbers from the normal distribution

(import (srfi 1))

(define norm (make-normal-generator 1 2))
(define samples (generator->list norm 1000))
(/ (fold + 0 samples) (length samples)) ; -> 0.925

License

2020 Arvydas Silanskas, Bradley Lucier, Linas Vepštas, John Cowan 2024 Peter McGoron

Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

Version History