1:- module(plrand, [
2 get_rnd_state/1 % -state
3 , set_rnd_state/1 % +state
4 , is_rnd_state/1 % +state
5 , init_rnd_state/1 % -state
6 , with_rnd_state/1 % +phrase(state)
7 , with_brs/2 % +varname, +phrase(state)
8 , init_brs/1 % +varname
9 , randomise_brs/1 % +varname
10 , randomise/1 % -state
11 , init_jump/2 % +integer, -jump
12 , double_jump/2 % +jump, -jump
13 , spawn/3 % -state, +state, -state
14 , jump/3 % +jump, +state, -state
15
16 , rnd_state_term/2
17 , run_rnd_state/3
18
19 , stream_init/3 % +state, +integer, -stream
20 , stream_split/3 % +stream, -stream, -stream
21
22 , sample_Single_/1 % -float
23 , sample_Double_/1 % -float
24
25 , log_prob_dirichlet/3 % +list(nonneg), +list(nonneg), -number
26 , mean_log_dirichlet/2 % +list(nonneg), -list(number)
27 , log_partition_dirichlet/2 % +list(nonneg), -number
28 , kldiv_dirichlet/3 % +list(nonneg), +list(nonneg), -number
29 , lngamma/2
30 , digamma/2
31 ]).
89:- use_foreign_library(foreign(plrand)). 90:- meta_predicate with_rnd_state( ), run_rnd_state( , , ), with_brs( , ).
toplevel_mode
to recursive. 100with_brs(N,G) :-
101 b_getval(N, S1), call_dcg(G,S1,S2),
102 b_setval(N, S2).
106init_brs(N) :- init_rnd_state(S), b_setval(N, S).
110randomise_brs(N) :- randomise(S), b_setval(N, S).
140with_rnd_state(P) :- get_rnd_state(S1), call_dcg(P,S1,S2), set_rnd_state(S2).
147rnd_state_term(RS,T) :-
148 ( nonvar(RS) -> rnd_state_to_term(RS,T)
149 ; ground(T) -> term_to_rnd_state(T,RS)
150 ).
state
), it is converted to the blob representation (type state
) and the final
state is converted back from term representation to get State2.159run_rnd_state(P,S1,S2) :- functor(S1,rs,7), !, 160 term_to_rnd_state(S1,R1), 161 call_dcg(P,R1,R2), 162 rnd_state_to_term(R2,S2). 163 164run_rnd_state(P,S1,S2) :- is_rnd_state(S1), !, call_dcg(P,S1,S2).
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.
228stream_init(State,E,stream(State,Jump)) :- init_jump(E,Jump).
235stream_split(stream(S0,J0),stream(S0,J1),stream(S1,J1)) :- !,
236 jump(J0,S0,S1), double_jump(J0,J1).
252log_prob_dirichlet(A,X,P) :-
253 length(A,N),
254 log_prob_Dirichlet(N,A,X,P).
259mean_log_dirichlet(A,X) :-
260 length(A,N),
261 mean_log_Dirichlet(N,A,X).
sum(map(gammaln,Alphas))
- gammaln(sum(Alphas))
. 266log_partition_dirichlet(A,Z) :-
267 length(A,N),
268 log_partition_Dirichlet(N,A,Z).
271kldiv_dirichlet(A,B,D) :- 272 length(A,N), length(B,N), 273 kldiv_Dirichlet(N,A,B,D). 274 275% kldiv_dirichlet(A,B,D) :- 276% log_partition_dirichlet(A,ZA), 277% log_partition_dirichlet(B,ZB), 278% mean_log_dirichlet(A,PsiA), 279% maplist(sub,B,A,DA), 280% map_sum(mul,DA,PsiA,DD), 281% D is ZB - ZA + DD.
Skippable, splittable psuedorandom generator
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
and ajump
.Available but not exported