:- source. :- style_check(all). :- module(clpbn_pgrammar, [grammar_to_atts/1, grammar_prob/2, grammar_mle/2, init_pcg_solver/4, run_pcg_solver/3, pcg_init_graph/0 ]). :- load_files(library(clpbn), [if(not_loaded), silent(true)]). :- use_module(library(lists), [sum_list/2]). :- use_module(library(matrix), [matrix_new/3, matrix_add/3, matrix_get/3, matrix_op/4, matrix_op_to_all/4, matrix_set_all/2 ]). :- op(600, xfy,'::'). :- dynamic id/4, dist_id/2, new_proof/2. :- meta_predicate grammar_prob(:,-), grammar_mle(:,-), grammar_to_atts(:). grammar_prob(M:S, P) :- !, grammar_prob(S, M, P). grammar_prob(S, P) :- source_module(M), grammar_prob(S, M, P). grammar_prob(S,M,P) :- nb_setval(grammar_fast,on), get_internal(S, InternalS, Proof), findall(P,path_prob(M:InternalS,Proof,P),Ps), nb_setval(grammar_fast,off), sum_list(Ps, P). path_prob(InternalS,Proof,P) :- call(InternalS), extract_probability(Proof, P). grammar_mle(M:S, P) :- !, grammar_mle(S, M, P). grammar_mle(S, P) :- source_module(M), grammar_mle(S, M, P). grammar_mle(S,M,P) :- nb_setval(grammar_fast,on), nb_setval(best,p(0.0,_)), get_internal(S, InternalS, Proof), call(M:InternalS), extract_probability(Proof, P), nb_getval(best,p(P0,_)), P > P0, nb_setval(best,p(P,S)), fail. grammar_mle(S,_,P) :- nb_setval(grammar_fast,off), nb_getval(best,p(P,S)), P > 0.0. user:term_expansion((P::H --> B), Goal) :- functor(H,A0,_), % a-->b to a(p(K,P,C,[Cs])) --> b(Cs) convert_to_internal(H, B, IH, IB, Id), expand_term((IH --> IB),(NH :- NB)), prolog_load_context(module, Mod), functor(NH,N,A), functor(EH,N,A), EH =.. [N|Args], build_rule_name(A0,NRuleName), EH1 =.. [NRuleName,Choice|Args], tail2(Args,LArgs), Key =.. [A0|LArgs], Args = [_|RArgs], H0 =.. [A0|RArgs], add_to_predicate(Mod:EH1,Mod:EH,Mod:H0,NH,NB,Key,Choice,P,Id,Goal). add_to_predicate(M:EH1,M:EH,_,NH,NB,Key,Choice,P,Id,(EH1:-NB)) :- predicate_property(M:EH1,number_of_clauses(I)), !, Choice is I+1, assert_static(M:ptab(EH,Choice,P)), new_id(Key,P,Choice,Id), EH = NH. add_to_predicate(M:EH1,M:EH,M:H0,NH,NB,Key,Choice,P,Id,(EH1:-NB)) :- % interface predicate assert_static(M:(H0 :- EH)), % now ensure_tabled works. ensure_tabled(M,H0,EH), assert_static(M:(EH :- clpbn_pgrammar:p_rule(M,EH,Key,Choice), M:EH1)), Choice = 1, new_id(Key,P,Choice,Id), assert_static(M:ptab(EH,Choice,P)), EH=NH. p_rule(_,_,_,_) :- nb_getval(grammar_fast,on), !. p_rule(M,EH,Key,Choice) :- all_tabs(M,EH,Dom,Opt), { AttVar = Key with p(Dom,Opt) }, Choice = AttVar. ensure_tabled(M,H0,EH) :- predicate_property(M:H0, tabled), !, functor(EH,N,Ar), table(M:N/Ar). ensure_tabled(_,_,_). build_internal(N,NInternal) :- atom_concat(N,'__internal',NInternal). build_rule_name(N,NRule) :- atom_concat(N,'__rule',NRule). convert_to_internal(Head, Body, NH, NBody, Id) :- convert_body_to_internal(Body, NBody, LGoals, []), Head =.. [Na|Args], build_internal(Na,NaInternal), NH =.. [NaInternal,p(Id,LGoals)|Args]. convert_body_to_internal((B1,B2), (NB1,NB2)) --> !, convert_body_to_internal(B1,NB1), convert_body_to_internal(B2,NB2). convert_body_to_internal([A], [A]) --> !. convert_body_to_internal({A}, {A}) --> !. convert_body_to_internal(B, IB) --> [V], { B =.. [Na|Args], build_internal(Na,NaInternal), IB =.. [NaInternal,V|Args] }. new_id(Key,P,Choice,Id) :- ( predicate_property(id(_,_,_,_),number_of_clauses(Id)) -> true ; Id = 0 ), assert(id(Id,Key,P,Choice)). all_tabs(M,EH,Dom,Ps) :- findall(P,M:ptab(EH,_,P),Ps), build_dom(Dom,1,Ps). build_dom([],_,[]). build_dom([I|Dom],I,[_|Ps]) :- I1 is I+1, build_dom(Dom,I1,Ps). tail2([A,B],[A,B]) :- !. tail2([_|Args],LArgs) :- tail2(Args,LArgs). get_internal(S, InternalS, Arg) :- S =.. [N|Args], build_internal(N, NInternal), InternalS =.. [NInternal, Arg|Args]. extract_probability(p(Id,Goals), P) :- id(Id,_,P0,_), LogP0 is log(P0), extract_logprobability(Goals, LogP0, LogP), P is exp(LogP). extract_logprobability(p(Id, Goals), LogP) :- id(Id,_,P0,_), LogP0 is log(P0), extract_logprobability(Goals, LogP0, LogP). extract_logprobability([], LogP, LogP). extract_logprobability([P1|Ps], LogP0, LogP) :- extract_logprobability(P1, LogDP), LogPI is LogDP+LogP0, extract_logprobability(Ps, LogPI, LogP). grammar_to_atts(M:S) :- !, grammar_to_atts(S, M). grammar_to_atts(S) :- source_module(M), grammar_to_atts(S, M). grammar_to_atts(S, M) :- nb_setval(grammar_fast,on), get_internal(S, InternalS, Proof), path_choices(M:InternalS,Proof). path_choices(InternalS, Proof) :- new_id(Id), call(InternalS), /* use Ids because we may have repeated examples */ assert(new_proof(Id,Proof)). new_id(Id) :- (nb_getval(grammar_id,Id) -> I1 is Id+1, nb_setval(grammar_id,I1) ; nb_setval(grammar_id,1), Id = 0 ). find_dom(K, Vs, Ps) :- findall(V,id(_,K,_,V),Vs), gen_ps(Vs, Ps). gen_ps([], []). gen_ps([_|Vs], [1.0|Ps]) :- gen_ps(Vs, Ps). init_pcg_solver(_, _, _, _). run_pcg_solver(LVs, LPs, _) :- init_prob_array(Array, ExArray), add_proofs_to_array(Array, ExArray), matrix:matrix_to_list(Array,L), writeln(L), out_to_vs(LVs, LPs, Array). add_proofs_to_array(Array, ExArray) :- nb_getval(grammar_id,IdMax), from(0,IdMax,Id), matrix_set_all(ExArray,0.0), sum_proofs(Id, ExArray), % matrix:matrix_to_list(ExArray,L0), writeln(Id:L0), matrix_op(ExArray, Array, +, Array), % matrix:matrix_to_list(Array,L0),writeln(i:L0), fail. add_proofs_to_array(_,_). from(I,_,I). from(I0,Id,I) :- I1 is I0+1, I1 < Id, from(I1,Id,I). sum_proofs(Id, ExArray) :- findall(P, add_proof(Id, ExArray, P), Ps), sum_list(Ps,TotP), matrix_op_to_all(ExArray,/,TotP,ExArray). add_proof(Id, ExArray, P) :- new_proof(Id,Proof), extract_probability(Proof, P), add_to_array(Proof, P, ExArray). add_to_array(p(Id, Goals), P, Array) :- add(Id, P, Array), add_to_array_goals(Goals, P, Array). add_to_array_goals([], _, _). add_to_array_goals([G|Goals], P, Array) :- add_to_array(G, P, Array), add_to_array_goals(Goals, P, Array). init_prob_array(Array, ExArray) :- predicate_property(id(_,_,_,_),number_of_clauses(Cls)), matrix_new(floats, [Cls], Array), matrix_new(floats, [Cls], ExArray). add(Id, P, Array) :- matrix_add(Array, [Id], P). out_to_vs([], [], _). out_to_vs([[V]|LVs], [Ps|LPs], Array) :- clpbn:get_atts(V, [key(Key)]), findall(P,count_for_key(Key,P,Array),Ps), out_to_vs(LVs, LPs, Array). count_for_key(Key,P,Array) :- id(Id,Key,_,_), matrix_get(Array, [Id], P). % generate attributed variables to make EM happy. % just as few as possible % pcg_init_graph :- setof(K,I^P^S^id(I,K,P,S),Ks), generate_atts(Ks). generate_atts([]). generate_atts([Key|KVs]) :- find_dom(Key, Dom, Ps), { _ = Key with p(Dom,Ps) }, generate_atts(KVs).