:- use_module(library(dcg_shell)). :- use_module(library(dcg_pair)). :- use_module(library(dcg_core)). :- use_module(library(data/store)). :- use_module(library(plrand)). :- use_module(library(prob/crp)). /* This is an example of how to build Dirichlet processes using the tools in plrand and crp. It works but setting up a DCG to manage the states of the CRPs and the state of the random generator. Once in the DCG (using dcgshell for an interactive DCG prompt) you can add observations and sample conditionally on those observations. For example: == ?- run. user: call_dcg (dcg) >> sample(dp(3,binomial(0.5,100)), DP), seqmap_n(9, sample(DP), X). DP = crp(dp(3), binomial(0.5, 100), 13) X = [48, 54, 49, 42, 48, 48, 45, 52, 42] user: call_dcg (dcg) >> sample(counter,C), sample(py(2,0.5,C), DP), seqmap_n(9, sample(DP), X). C = counter(21) DP = crp(py(2, 0.5), counter(21), 22) X = [0, 1, 2, 1, 3, 4, 5, 5, 1] == NB. it requires the dcgutils and genutils packs to be installed. */ run :- store_new(Store), with_rnd_state(run_left(dcgshell, Store, _)). sample(dp(Conc, Base), crp(dp(Conc),Base,Ref)) --> {empty_classes(Classes)}, \< store_add(Classes, Ref). sample(py(Conc, Disc, Base), crp(py(Conc,Disc),Base,Ref)) --> {empty_classes(Classes)}, \< store_add(Classes, Ref). sample(counter, counter(Ref)) --> \< store_add(0, Ref). sample(normal, X) --> \> plrand:sample_Normal(X). sample(exponential, X) --> \> plrand:sample_Exponential(X). sample(gamma(A), X) --> \> plrand:sample_Gamma(A,X). sample(zeta(S), X) --> \> plrand:sample_Zeta(S,X). sample(binomial(P,N), X) --> \> plrand:sample_Binomial(P,N,X). sample(counter(Ref), X) --> \< store_get(Ref, X), \< store_apply(Ref, succ). sample(crp(GEM,Base,Ref), X) --> \< store_get(Ref, Classes), \> crp_sample(GEM, Classes, Action), sample_action(Action, Base, Ref, X). sample_action(new, Base, Ref, X) --> sample(Base, X), \< store_apply(Ref, add_class(X,_)). sample_action(old(X,N), _, Ref, X) --> \< store_apply(Ref, inc_class(N)). prob(normal, _, 0) --> nop. prob(exponential, _, 0) --> nop. prob(gamma(_), _, 0) --> nop. prob(zeta(S), X, P) --> {plrand:prob_Zeta(S,X,P)}. prob(binomial(Q,N), X, P) --> {plrand:prob_Binomial(Q,N,X,P)}. prob(counter(Ref), X, P) --> \< store_get(Ref,Y), {delta(X,Y,P)}. prob(crp(GEM,Base,Ref), X, P) --> prob(Base, X, P0), \< store_get(Ref, Classes), { crp_prob(GEM, Classes, X, P0, P) }. delta(X,X,1). delta(X,Y,0) :- dif(X,Y). observe(crp(GEM,Base,Ref), X) --> prob(Base, X, P), \< store_get(Ref, Classes), \> crp_sample_obs(GEM, Classes, X, P, Action), {writeln(observe_action(Action))}, \< store_apply(Ref, obs_action(Action, X)). obs_action(new, X) --> add_class(X, _). obs_action(old(N), _) --> inc_class(N). resample(CRP) --> {CRP=crp(_,_,Ref)}, \< store_get(Ref, classes(_,Counts,Values)), seqmap(resample_class(CRP),Counts,Values). resample_class(CRP, Count, X) --> rep(Count, resample_value(CRP, X)). resample_value(CRP, X) --> {writeln(reseating(X))}, unobserve(CRP, X), observe(CRP, X). unobserve(crp(_,_,Ref), X) --> \< store_get(Ref, Classes), \> crp_sample_rm(Classes, X, N), \< store_apply(Ref, remove_from_class(N)). remove_from_class(N) --> dec_class(N,C,_), ({C>0}; {C=0}, remove_class(N)). gem_samples(gamma(A,B), crp(dp(Conc), _, Ref), N, Concs) --> \< store_get(Ref, classes(_,Counts,_)), {dp_sampler_teh(gamma(A,B), [Counts], Sampler)}, \> collect_dp_samples(N, Sampler, Conc, Concs). collect_dp_samples(0, _, _, []) --> []. collect_dp_samples(N, Sampler, Conc0, [Conc1|Concs]) --> {succ(M,N)}, call(Sampler, dp(Conc0), dp(Conc1)), collect_dp_samples(M, Sampler, Conc1, Concs).