This module provides an interface to Pierre Ecuyer's pseudorandom generator
library RngStream, which is a high-quality, long period pseudorandom generator
that can do the neat trick of quickly skipping ahead an arbitrary number of samples
in the stream without actually generating all the samples in between. This
capability is used to implement a stream of random bits that can be split
recursively into 'pseudoindependent' substreams.
Types
- state
- The state of a random generator, as a blob atom.
- state_term
- A state represented as an ordinary Prolog term that can be written as text.
- jump
- A blob representing an operator to advance a state by several steps
- stream
- A splittable stream, containing a
state
and a jump
.
- prob
- A floating point number between 0 and 1.
Available but not exported
sample_Uniform01(-float)//
sample_Raw(-integer)//
sample_Normal(-float)//
sample_Exponential(-nonneg)//
sample_Beta(+nonneg, +nonneg, -nonneg)//
sample_Gamma(+nonneg, -float)//
sample_Poisson(+nonneg, -natural)//
sample_Zeta(+nonneg, -natural)//
sample_Discrete(+nonneg, +list(prob), -natural)//
sample_DiscreteF(+nonneg, +array(prob), -natural)//
sample_Dirichlet(+nonneg, +list(nonneg), -list(prob))//
sample_DirichletF(+nonneg, +array(nonneg), -array(prob))//
sample_Stable(+float, +float, -float)//
sample_Binomial(+prob, +natural, -natural)//
prob_Uniform01(+float, -prob)
prob_Normal(+float, -prob)
prob_Exponential(+nonneg, -prob)
prob_Beta(+nonneg, +nonneg, +nonneg, -prob)
prob_Gamma(+nonneg, +float, -prob)
prob_Poisson(+nonneg, +natural, -prob)
prob_Zeta(+nonneg, +natural, -prob)
prob_Discrete/4
prob_Dirichlet/4
prob_Binomial/4
logprob_Dirichlet/4
- copyright
- - Samer Abdallah (2009--2016)
- with_brs(N:atom, G:dcg(rndstate)) is det
- Runs goal G as a DCG goal with RNG state from a thread-local bactrackable
gobal variable name N.
The final state is stored in the global variable, but any
subsequent failure will restore the previous value. If using in a thread
other than main, you must call init_rnd_state/0 to initialise the global
variable. NB, you will probably want to set the Prolog flag
toplevel_mode
to recursive.
- init_brs(+Name) is det
- Initialise thread local backtrackable global variable with default RNG state.
- randomise_brs(+Name) is det
- Randomise thread local backtrackable global variable using randomise/1.
- get_rnd_state(-State:state) is det
- Unifies State with the current global RNG state.
@see set_rnd_state/1
- set_rnd_state(+State:state) is det
- Sets the globab RNG state to State.
@see get_rnd_state/1
- init_rnd_state(-State:state) is det
- Unifies State with the state that was set at load time.
- randomise(-State:state) is det
- Returns a truly random state by reading from /dev/random.
- is_rnd_state(+State:state) is semidet
- Succeeds if State is a BLOB atom representing a random generator state.
- with_rnd_state(Cmd:phrase(state)) is nondet
- Runs DCG goal Cmd using the current global RNG state as the initial state
the global RNG state afterwards.
- rnd_state_term(+State:state, -Term:state_term) is det
- rnd_state_term(-State:state, +Term:state_term) is det
- Convert between blob and term representation of random state.
- run_rnd_state(Cmd:phrase(state), +State1:state, -State2:state) is nondet
- run_rnd_state(Cmd:phrase(state), +State1:state_term, -State2:state_term) is nondet
- Runs DCG phrase Cmd as with call_dcg/3, except that, if State1 is in the term representation
(type
state
), it is converted to the blob representation (type state
) and the final
state is converted back from term representation to get State2.
- init_jump(+E:integer, -Jump:jump) is det
- Unifies Jump with a BLOB atom representing an operator to jump forwards
2^E steps in the stream of random numbers. The generator has a period
of about 2^191. Operators for jumping ahead by 2^76 and 2^127 are
precomputed and so can be returned faster. The resulting BLOB can be
used with jump/3 to advance any given random generator state.
- double_jump(+Jump1:jump, -Jump2:jump) is det
- Unifies Jump2 with an operator that jumps ahead twice as far Jump1,
ie if Jump1 jumps by 2^E, then Jump2 jumps by 2^(E+1). Jump operators
can be created by init_jump/2 and applied by jump/3.
- jump(+Jump:jump, +State1:state, -State2:state) is det
- Advances random generator state represented in State1 by the number
of steps represented by Jump, unifying State2 with the result.
- See also
- - double_jump/2
- - init_jump/2
- spawn(-New:state, +Orig:state, -Next:state) is det
- Samples enough bits from Orig to specify a new generator state New,
leaving the original generator in Next. If generator states represent
streams of random numbers, then you can think of it as sampling a whole
stream of values instead of just one value.
Note: New is likely to point to a new point in the original stream
far away from Orig and Next, simply because the period of the generator
is so large (about 2^191) but there is no guarantee of this. Therefore, it's
possible (but unlikely) that New might produce a stream that overlaps
significantly with samples drawn from Next. If you need to be sure
that New is a long way from Orig and Next, then use jump/3 instead.
- Arguments:
-
New | - is the state of the newly created generator. |
Orig | - is the state of the source generator, the original stream. |
Next | - is the state of the source generator after extracting New. |
- stream_init(+State:state, +E:integer, -Stream:stream) is det
-
stream ---> stream(state, integer).
[EXPERIMENTAL] Used to initialise a splittable stream. The idea is that
a stream of random number can be recursively split into many substreams,
each of which will not overlap unless very many samples are drawn.
For example init_rnd_state(S), stream_init(S,76,Z)
produces a stream such that the first split jumps 2^76 steps along.
Thus, 2^76 samples can be drawn from either before overlap occurs.
Since the period of the generator is more than 2^190, there can be up to
114 levels of recursive splitting, resulting in up to 2^114 substreams.
- Arguments:
-
State | - is the initial state of the generator. |
E | - is a nonnegative integer such that, when the stream is first split,
the new substream begins 2^E steps along the sequence. Subsequent splits
will jump twice as far each time. |
Stream | - is the new stream (a term) |
- stream_split(+Stream1, -Stream2, -Stream3) is det
- [EXPERIMENTAL] Stream1 is split into independent streams Stream2 and Stream3.
Stream2 is actually the same as Stream1. Stream3 is a window on the same strem,
but starting a long way down the sequence.
- sample_Single_(-Float) is det
- Samples a single precision floating point value in [0,1) using the
internal (global) random generator state. It consumes one 32 bit value
from the generator. This is the fasted way to generate a random value
using this library.
- sample_Double_(-Float) is det
- Samples a double precision floating point value in [0,1) using the
internal (global) random generator state. It consumes two 32 bit values
from the generator.
- mean_log_dirichlet(+Alphas:list(nonneg), -X:list(number)) is det
- Compute the expectation of the component-wise log of a Dirichilet
distributed vector represented as a list.
- log_partition_dirichlet(+Alphas:list(nonneg), -X:number) is det
- Compute the log of the normalisation constant of the Dirichlet PDF with
parameters Alphas,
sum(map(gammaln,Alphas))
- gammaln(sum(Alphas))
.
- kldiv_dirichlet(+A:list(nonneg), +B:list(nonneg), -D:number) is det
Undocumented predicates
The following predicates are exported, but not or incorrectly documented.
- log_prob_dirichlet(Arg1, Arg2, Arg3)
- lngamma(Arg1, Arg2)
- digamma(Arg1, Arg2)