2608 lines
		
	
	
		
			62 KiB
		
	
	
	
		
			Prolog
		
	
	
	
	
	
			
		
		
	
	
			2608 lines
		
	
	
		
			62 KiB
		
	
	
	
		
			Prolog
		
	
	
	
	
	
/*
 | 
						|
 | 
						|
RIB
 | 
						|
 | 
						|
Copyright (c) 2011, Fabrizio Riguzzi and Nicola di Mauro
 | 
						|
 | 
						|
*/
 | 
						|
:-multifile setting/2,mode/2,modeh/2,modeb/2,neg/1.
 | 
						|
%:- set_prolog_flag(profiling,on).
 | 
						|
%:- set_prolog_flag(debug,on).
 | 
						|
:- set_prolog_flag(discontiguous_warnings,on).
 | 
						|
:- set_prolog_flag(single_var_warnings,on).
 | 
						|
%:-yap_flag(gc_trace,very_verbose).
 | 
						|
%:- source.
 | 
						|
:- use_module(inference_ib,
 | 
						|
  [build_network/5,
 | 
						|
  get_prob/3,
 | 
						|
  get_CL/3,
 | 
						|
  remove_head/2,
 | 
						|
  get_atoms/2,
 | 
						|
  find_deriv_inf1/2,
 | 
						|
  find_atoms_head/3]).
 | 
						|
 | 
						|
:-use_module(library(lists)).
 | 
						|
:-use_module(library(rbtrees)).
 | 
						|
:-use_module(library(random)).
 | 
						|
:-set_prolog_flag(unknown,fail).
 | 
						|
 | 
						|
%:-use_module(library(lpadsld)).
 | 
						|
 | 
						|
:-dynamic setting/2.
 | 
						|
 | 
						|
/* Total number of examples in case in which the models in the kb file contain
 | 
						|
a prob(P). fact. In that case, one model corresponds to sample_size*P examples
 | 
						|
*/
 | 
						|
setting(sample_size,1000). 
 | 
						|
setting(setrand,rand(1230,45,123)).
 | 
						|
 | 
						|
setting(verbosity,1).
 | 
						|
setting(minimal_step,0.005).
 | 
						|
setting(maximal_step,0.1).
 | 
						|
setting(depth_bound,3).
 | 
						|
setting(logsize_fraction,0.9).
 | 
						|
/* value assigned to log 0
 | 
						|
*/
 | 
						|
setting(delta,-10).
 | 
						|
 | 
						|
setting(epsilon_fraction,100).
 | 
						|
 | 
						|
/* maximum number of non-ground rules 
 | 
						|
*/
 | 
						|
setting(max_rules,6000).
 | 
						|
/* maximum number of variables in an output rule
 | 
						|
*/
 | 
						|
 | 
						|
 | 
						|
/* Data structures:
 | 
						|
 | 
						|
array qy: Q(y)
 | 
						|
array q: Q(ch|y), for each y q store a red black tree with ch(N,S) as key
 | 
						|
array p: P(N), for each rule N store d(Probs,Atoms)
 | 
						|
PAX: rb tree with atoms as key and list of parents (ch(N,S)) as values
 | 
						|
CH: list of choice variables, each of the form ch(N,S) where N is the rule
 | 
						|
number and S is a substitution that ground rule N
 | 
						|
R: list of elemtns N-Inst where N is a rule number and Inst is a list of
 | 
						|
instantiations
 | 
						|
 | 
						|
Storage of examples:
 | 
						|
an extra argument is added to each ground atom to store the example id (integer)
 | 
						|
atom a(b,c,d) that is true in interpretation 10 is asserted as
 | 
						|
a(10,a,b,c,d)
 | 
						|
*/
 | 
						|
 | 
						|
 | 
						|
ib_par(File):-
 | 
						|
  setting(setrand,K),
 | 
						|
  setrand(K),
 | 
						|
  generate_file_names(File,FileKB,FileOut,FileL,FileLPAD,FileBG),
 | 
						|
  reconsult(FileL),
 | 
						|
        (file_exists(FileBG)->
 | 
						|
                reconsult(FileBG)
 | 
						|
        ;
 | 
						|
                true
 | 
						|
        ),
 | 
						|
  load_models(FileKB),
 | 
						|
  retractall(hb(_,_,_)),
 | 
						|
  ex(NS),
 | 
						|
  set(sample_size,NS),
 | 
						|
  load_initial_model(FileLPAD,Model),!,
 | 
						|
  randomize(Model,Model0),
 | 
						|
  set(verbosity,3),
 | 
						|
  statistics(runtime,[_,_]),  
 | 
						|
  assert_model(Model0),  
 | 
						|
  write_model(Model0,user_output),
 | 
						|
  compute_parameters_IB(Model0,Model1,I,LogSize),
 | 
						|
  statistics(runtime,[_,CT]),
 | 
						|
  CTS is CT/1000,
 | 
						|
  format("Execution time ~f LogSize ~f Final I ~f~n",[CTS,LogSize,I]),
 | 
						|
  listing(setting/2),
 | 
						|
  format("Model:~n",[]),
 | 
						|
  write_model(Model1,user_output),
 | 
						|
  open(FileOut,write,Stream),
 | 
						|
  format(Stream,"/* Execution time ~f LogSize ~f Final I ~f~n",[CTS,LogSize,I]),
 | 
						|
  tell(Stream),
 | 
						|
  listing(setting/2),
 | 
						|
  format(Stream,"*/~n",[]),
 | 
						|
  write_model(Model1,Stream),
 | 
						|
  told.
 | 
						|
 | 
						|
/* checks whether two variable substitutions are the same,
 | 
						|
independently of the variable names */
 | 
						|
match_subs([],_S1):-!.
 | 
						|
 | 
						|
match_subs([_V1=S|TS],[_V2=S|TS1]):-
 | 
						|
  match_subs(TS,TS1).
 | 
						|
  
 | 
						|
/* computes the parameters of a model by using the information bottleneck
 | 
						|
*/
 | 
						|
compute_parameters_IB(Model0,Model1,I2,LogSize):-
 | 
						|
  build_network_IB(CH,PAX,T,TCh,R,LogSize),
 | 
						|
  my_set_value(ch,CH),
 | 
						|
  my_set_value(pax,PAX),
 | 
						|
  my_set_value(t,T),  
 | 
						|
  my_set_value(tch,TCh),
 | 
						|
  (CH=[]->
 | 
						|
    Model1=Model0
 | 
						|
  ;
 | 
						|
    length(CH,LCH),
 | 
						|
    format("Logsize ~f ground clauses ~d~n",[LogSize,LCH]),
 | 
						|
    ex(NEx),
 | 
						|
    array(q,NEx),
 | 
						|
    array(qt,NEx),
 | 
						|
    build_q_table(CH),
 | 
						|
    build_qt_table(T),
 | 
						|
    static_array(qy,NEx,float),
 | 
						|
    build_q_Y_table(0,NEx),
 | 
						|
    build_p_table(Model0),
 | 
						|
    rb_new(Q_ch0),
 | 
						|
    compute_Q_ch(CH,Q_ch0,Q_ch1),
 | 
						|
    rb_new(Q_t0),
 | 
						|
    compute_Q_t(T,Q_t0,Q_t1),
 | 
						|
    compute_I(NEx,CH,Q_ch1,T,Q_t1,I1),
 | 
						|
    compute_Nr(R,NR),
 | 
						|
    iterate_IB_par(0.0,I1,I2,1,Q_ch1,Q_t1,R,NR,LogSize,Model0),
 | 
						|
    build_new_model(Model0,Model1),
 | 
						|
    flush_output
 | 
						|
  ).
 | 
						|
 | 
						|
/* updates the model with the distribution stored in the array p (P 
 | 
						|
distribution after the optimization)
 | 
						|
*/
 | 
						|
build_new_model([],[]).
 | 
						|
 | 
						|
build_new_model([rule(N,V,NH,HL,BL,LogF)|T],[rule(N,V,NH,HL1,BL,LogF)|T1]):-
 | 
						|
  my_get_value(ch,CH),
 | 
						|
  member(ch(N,_S),CH),!,
 | 
						|
  array_element(p,N,d(Distr,_Val)),
 | 
						|
  new_dist(HL,Distr,HL1),
 | 
						|
  build_new_model(T,T1).
 | 
						|
 | 
						|
build_new_model([H|T],[H|T1]):-
 | 
						|
  build_new_model(T,T1).
 | 
						|
/* given a head as a list of annotated atoms and a list of probabilities,
 | 
						|
returns the head with the annotations taken from the list of probabilities
 | 
						|
*/
 | 
						|
new_dist([],[],[]):-!.
 | 
						|
 | 
						|
new_dist([H:_P|HL],[P1|TP],[H:P1|HL1]):-
 | 
						|
  new_dist(HL,TP,HL1).
 | 
						|
 | 
						|
/* builds the initial Q(Y) table:
 | 
						|
it assigns to each example either
 | 
						|
1) the probability indicated for the example in the .kb file
 | 
						|
2) or 1/n if n is the number of examples
 | 
						|
*/
 | 
						|
build_q_Y_table(N,N):-!.
 | 
						|
 | 
						|
build_q_Y_table(N,NEx):-
 | 
						|
  (prob(N,P)->
 | 
						|
    true
 | 
						|
  ;
 | 
						|
    P is 1/NEx
 | 
						|
  ),
 | 
						|
  update_array(qy,N,P),
 | 
						|
  N1 is N+1,
 | 
						|
  build_q_Y_table(N1,NEx).
 | 
						|
 | 
						|
/* main cycle of parameter learning with ib
 | 
						|
*/  
 | 
						|
iterate_IB_par(Gamma,I,I,N,_Q_ch,_Q_t,_R,_NR,LogSize,_Model):-
 | 
						|
  setting(logsize_fraction,LF),
 | 
						|
 | 
						|
  (
 | 
						|
  Gamma>0.9999
 | 
						|
  ;I>LogSize*LF
 | 
						|
  ),
 | 
						|
  format("Iteration ~d~nGamma ~f~n I ~f~n",[N,Gamma,I]),
 | 
						|
  !.  
 | 
						|
 | 
						|
 | 
						|
iterate_IB_par(Gamma,I,I2,N,Q_ch,Q_t,R,NR,LogSize,Model):-
 | 
						|
  format("Iteration ~d~nGamma ~f~n I ~f~n",[N,Gamma,I]),
 | 
						|
  maximize_Q(Gamma,Q_ch,Q_t,R,LogSize,NR,Gamma1),
 | 
						|
  compute_Nr(R,NR1),
 | 
						|
  maximize_P(R,NR1),
 | 
						|
  ex(NEx),
 | 
						|
  rb_new(Q_ch0),
 | 
						|
  my_get_value(ch,CH),
 | 
						|
  compute_Q_ch(CH,Q_ch0,Q_ch1),
 | 
						|
  rb_new(Q_t0),
 | 
						|
  my_get_value(t,T),
 | 
						|
  compute_Q_t(T,Q_t0,Q_t1),
 | 
						|
  compute_I(NEx,CH,Q_ch1,T,Q_t1,I1),
 | 
						|
  N1 is N+1,
 | 
						|
  build_new_model(Model,Model1),
 | 
						|
  retract_model,
 | 
						|
  assert_model(Model1),
 | 
						|
  flush_output,
 | 
						|
  iterate_IB_par(Gamma1,I1,I2,N1,Q_ch1,Q_t1,R,NR1,LogSize,Model).
 | 
						|
 | 
						|
 | 
						|
/* computes the P distribution that maximizes the Lagrangian
 | 
						|
*/
 | 
						|
maximize_P([],[]):-!.
 | 
						|
 | 
						|
maximize_P([_N-_Inst|TR],[0.0|TNR]):-!,
 | 
						|
  maximize_P(TR,TNR).
 | 
						|
 | 
						|
maximize_P([N-_Inst|TR],[_NR|TNR]):-
 | 
						|
  def_rule_by_num(N,_V,_HL,_BL),!,
 | 
						|
  maximize_P(TR,TNR).
 | 
						|
 | 
						|
maximize_P([N-Inst|TR],[NR|TNR]):-
 | 
						|
  rule_by_num(N,_V,_NH,HL,_BL),
 | 
						|
  length(HL,LH),
 | 
						|
  list0(0,LH,Num0),  
 | 
						|
  ex(NEx),
 | 
						|
  compute_theta_num(0,NEx,Inst,N,Num0,Num),
 | 
						|
  divide(NR,Num,Theta),
 | 
						|
%  normalize(Theta,Theta1),
 | 
						|
  array_element(p,N,d(_,Val)),
 | 
						|
  update_array(p,N,d(Theta,Val)),
 | 
						|
  maximize_P(TR,TNR).
 | 
						|
 | 
						|
/* computes the numerator of \theta_{hd_r|true}, i.e.
 | 
						|
\sum_{s\in i(r)}\sum_{y}Q(y)Q(Ch_s=hd_r|y)bt(pa_{ch_s}[y])+\alpha(r,hd_r,true)=
 | 
						|
\sum_{s,ch_s\in i(r)}\mathcal{N}(s,hd_r)+\alpha(r,hd_r,true)=
 | 
						|
\mathcal{N}(r,hd_r)
 | 
						|
*/
 | 
						|
compute_theta_num(N,N,_Inst,_N,Num,Num):-!.
 | 
						|
 | 
						|
compute_theta_num(Y,NEx,Inst,N,Num0,Num1):-
 | 
						|
  array_element(qy,Y,Q_Y),
 | 
						|
  array_element(q,Y,Q_ch_Y_par),
 | 
						|
  find_true_inst_unseen(Inst,N,Y,TInst),
 | 
						|
  compute_theta_term(TInst,Y,N,Q_Y,Q_ch_Y_par,Num0,Num2),
 | 
						|
  Y1 is Y+1,
 | 
						|
  compute_theta_num(Y1,NEx,Inst,N,Num2,Num1).
 | 
						|
 | 
						|
/*   computes 
 | 
						|
\sum_{y}Q(y)Q(Ch_s=hd_r|y)bt(pa_{ch_s}[y])+\alpha(r,hd_r,true)=
 | 
						|
\mathcal{N}(s,hd_r)+\alpha(r,hd_r,true)
 | 
						|
*/
 | 
						|
compute_theta_term([],_Y,_N,_Q_Y,_Q_ch_Y_par,Term,Term):-!.
 | 
						|
 | 
						|
compute_theta_term([S|TS],Y,N,Q_Y,Q_ch_Y_par,Term0,Term1):-
 | 
						|
  rb_lookup(ch(N,S),Q_ch_Y,Q_ch_Y_par),
 | 
						|
  rule_by_num(N,Sub,_NH,_HL,BL),
 | 
						|
  match_subs(S,Sub),
 | 
						|
  prob_body(BL,Y,1,PTB,_B),
 | 
						|
  times(Q_Y,Q_ch_Y,TermS0),
 | 
						|
  times(PTB,TermS0,TermS),  
 | 
						|
  sum(Term0,TermS,Term2),
 | 
						|
  compute_theta_term(TS,Y,N,Q_Y,Q_ch_Y_par,Term2,Term1).
 | 
						|
  
 | 
						|
/* computes the Q distribution that maximizes the Lagrangian 
 | 
						|
*/
 | 
						|
maximize_Q(Gamma,Q_ch,Q_t,R,LogSize,NR,Gamma1):-
 | 
						|
  my_get_value(ch,CH),
 | 
						|
  my_get_value(pax,PAX),
 | 
						|
  my_get_value(t,T),
 | 
						|
  setting(delta,Delta),
 | 
						|
  ex(NEx),
 | 
						|
  compute_D(0,NEx,R,NR,D),
 | 
						|
  compute_Q_gradient(0,NEx,Gamma,Delta,Q_ch,Q_t,R,NR,CH,PAX,T,D,[],QGrad,[],IGrad,
 | 
						|
    [],QTGrad,[],ITGrad),
 | 
						|
  compute_step(QGrad,IGrad,QTGrad,ITGrad,LogSize,S),
 | 
						|
  setting(minimal_step,MinS),
 | 
						|
  setting(maximal_step,MaxS),
 | 
						|
  ((S<MinS;\+ S< +inf)->
 | 
						|
    S1=MinS
 | 
						|
  ;
 | 
						|
    (S>MaxS->
 | 
						|
      S1=MaxS
 | 
						|
    ;
 | 
						|
      S1=S
 | 
						|
    )
 | 
						|
  ),
 | 
						|
  format("Step: original ~f, adjusted ~f~n",[S,S1]),
 | 
						|
  Gamma1 is Gamma +S1,
 | 
						|
  update_Q(0,NEx,CH,QGrad,S1),
 | 
						|
  update_QT(0,NEx,T,QTGrad,S1).
 | 
						|
 | 
						|
/* computes I_Q(CH;Y)=
 | 
						|
\sum_y\sum_i\sum_{ch_i}Q(y)Q(ch_i|y)(\log Q(ch_i|y)-\log Q(ch_i))=
 | 
						|
(\sum_y\sum_i\sum_{ch_i}Q(y)Q(ch_i|y)\log Q(ch_i|y))-E_Q[\log Q(ch_i)]
 | 
						|
*/
 | 
						|
compute_I(NEx,CH,Q_ch,T,Q_t,I):-
 | 
						|
  compute_I(0,NEx,CH,Q_ch,T,Q_t,0,I0),
 | 
						|
  compute_Exp_Q_ch(CH,Q_ch,0,I1),
 | 
						|
  compute_Exp_Q_t(T,Q_t,0,I2),
 | 
						|
%  format("I0 ~f I1 ~f I2 ~f~n",[I0,I1,I2]),
 | 
						|
  I is I0+I1+I2.
 | 
						|
 | 
						|
compute_I(N,N,_CH,_Q_ch_par,_T,_Q_t,I,I):-!.
 | 
						|
 | 
						|
compute_I(Y,NEx,CH,Q_ch_par,T,Q_t_par,I0,I1):-
 | 
						|
  array_element(qy,Y,Q_Y),
 | 
						|
  array_element(q,Y,Q_ch_Y_par),
 | 
						|
  array_element(qt,Y,Q_t_Y_par),
 | 
						|
  compute_I_ch(CH,Q_ch_Y_par,Q_Y,0,ICH),
 | 
						|
  compute_I_t(T,Q_t_Y_par,Q_Y,0,IT),
 | 
						|
  I2 is I0+ICH+IT,
 | 
						|
  %format("Y ~d ICH ~f IT ~f~n",[Y,ICH,IT]),
 | 
						|
  Y1 is Y+1,
 | 
						|
  compute_I(Y1,NEx,CH,Q_ch_par,T,Q_t_par,I2,I1).
 | 
						|
 | 
						|
  
 | 
						|
/* computes -\sum_i E_Q[\log Q(Ch_i)]=-\sum_{ch_i}Q(ch_i)\log Q(ch_i)
 | 
						|
*/
 | 
						|
compute_Exp_Q_ch([],_Q_ch_par,I,I):-!.
 | 
						|
 | 
						|
compute_Exp_Q_ch([ch(N,_S)|T],Q_ch_par,I0,I1):-
 | 
						|
  def_rule_by_num(N,_V,_HL,_BL),!,
 | 
						|
  compute_Exp_Q_ch(T,Q_ch_par,I0,I1).
 | 
						|
 | 
						|
compute_Exp_Q_ch([CH|T],Q_ch_par,I0,I1):-
 | 
						|
  rb_lookup(CH,Q_ch,Q_ch_par),
 | 
						|
  compute_Exp_Q_ch_val(Q_ch,I0,I2),
 | 
						|
  compute_Exp_Q_ch(T,Q_ch_par,I2,I1).
 | 
						|
 | 
						|
compute_Exp_Q_t([],_Q_t_par,I,I):-!.
 | 
						|
 | 
						|
compute_Exp_Q_t([H|T],Q_t_par,I0,I1):-
 | 
						|
  rb_lookup(H,Q_t,Q_t_par),
 | 
						|
  I2 is I0-Q_t*log(Q_t)-(1-Q_t)*log(1-Q_t),
 | 
						|
  compute_Exp_Q_t(T,Q_t_par,I2,I1).
 | 
						|
 | 
						|
/* computes -E_Q[\log Q(Ch_i)]=-\sum_{ch_i}Q(ch_i)\log Q(ch_i)
 | 
						|
*/
 | 
						|
compute_Exp_Q_ch_val([],I,I):-!.
 | 
						|
 | 
						|
compute_Exp_Q_ch_val([Q_ch|T],I0,I1):-
 | 
						|
  I2 is I0-Q_ch*log(Q_ch),
 | 
						|
  compute_Exp_Q_ch_val(T,I2,I1).
 | 
						|
 | 
						|
/* computes \sum_i\sum_{ch_i}Q(y)Q(ch_i|y)\log Q(ch_i|y)
 | 
						|
*/
 | 
						|
compute_I_ch([],_Q_ch_Y_par,_Q_Y,I,I):-!.
 | 
						|
 | 
						|
compute_I_ch([ch(N,_S)|T],Q_ch_Y_par,Q_Y,I0,I1):-
 | 
						|
  def_rule_by_num(N,_V,_HL,_BL),!,
 | 
						|
  compute_I_ch(T,Q_ch_Y_par,Q_Y,I0,I1).
 | 
						|
 | 
						|
compute_I_ch([CH|T],Q_ch_Y_par,Q_Y,I0,I1):-
 | 
						|
  rb_lookup(CH,Q_ch_Y,Q_ch_Y_par),
 | 
						|
  compute_exp_I(Q_ch_Y,Q_Y,I0,I2),
 | 
						|
  compute_I_ch(T,Q_ch_Y_par,Q_Y,I2,I1).
 | 
						|
 | 
						|
compute_I_t([],_Q_t_Y_par,_Q_Y,I,I):-!.
 | 
						|
 | 
						|
compute_I_t([H|T],Q_t_Y_par,Q_Y,I0,I1):-
 | 
						|
  rb_lookup(H,Q_t_Y,Q_t_Y_par),
 | 
						|
  ((Q_t_Y=<0;Q_t_Y>1)->format("I ~p ~f~n",[H,Q_t_Y]);true),
 | 
						|
  I2 is I0+Q_Y*(Q_t_Y*log(Q_t_Y)+(1-Q_t_Y)*log(1-Q_t_Y)),
 | 
						|
  compute_I_t(T,Q_t_Y_par,Q_Y,I2,I1).
 | 
						|
 | 
						|
/* computes \sum_{ch_i}Q(y)Q(ch_i|y)\log Q(ch_i|y)
 | 
						|
*/
 | 
						|
compute_exp_I([],_Q_Y,I,I):-!.
 | 
						|
 | 
						|
compute_exp_I([Q_ch_Y|T0],Q_Y,I0,I1):-
 | 
						|
  I2 is I0+Q_ch_Y*Q_Y*log(Q_ch_Y),
 | 
						|
  compute_exp_I(T0,Q_Y,I2,I1).
 | 
						|
 | 
						|
/* computes the new values for the distribution Q(Ch|Y) given the gradient
 | 
						|
vector
 | 
						|
*/
 | 
						|
update_Q(NEx,NEx,_CH,[],_S):-!.
 | 
						|
 | 
						|
update_Q(Y,NEx,CH,[QG|TQG],S):-
 | 
						|
  array_element(q,Y,Q_ch_Y_par),
 | 
						|
  update_Q_Y(CH,Q_ch_Y_par,QG,S,Q_ch_Y_par1),
 | 
						|
  update_array(q,Y,Q_ch_Y_par1),
 | 
						|
  Y1 is Y+1,
 | 
						|
  update_Q(Y1,NEx,CH,TQG,S).
 | 
						|
 | 
						|
 | 
						|
/* computes the new values for the distribution Q(Ch|Y) given the gradient
 | 
						|
vector and an example Y
 | 
						|
*/
 | 
						|
update_Q_Y([],Q_ch_Y_par,[],_S,Q_ch_Y_par):-!.
 | 
						|
 | 
						|
update_Q_Y([ch(N,_S)|TCH],Q_ch_Y_par,TQG,S,Q_ch_Y_par1):-
 | 
						|
  def_rule_by_num(N,_V,_HL,_BL),!,
 | 
						|
  update_Q_Y(TCH,Q_ch_Y_par,TQG,S,Q_ch_Y_par1).
 | 
						|
 | 
						|
update_Q_Y([CH|TCH],Q_ch_Y_par,[HQG|TQG],S,Q_ch_Y_par1):-
 | 
						|
  rb_lookup(CH,Dist,Q_ch_Y_par),
 | 
						|
  times(S,HQG,Delta),
 | 
						|
  %fomat("Delta ~p~n",[Delta]),
 | 
						|
  sum_lower(Dist,Delta,Dist1),
 | 
						|
  normalize(Dist1,Dist2),
 | 
						|
  rb_update(Q_ch_Y_par,CH,Dist2,Q_ch_Y_par2),
 | 
						|
  update_Q_Y(TCH,Q_ch_Y_par2,TQG,S,Q_ch_Y_par1).
 | 
						|
 | 
						|
update_QT(NEx,NEx,_T,[],_S):-!.
 | 
						|
 | 
						|
update_QT(Y,NEx,T,[QG|TQG],S):-
 | 
						|
  array_element(qt,Y,Q_t_Y_par),
 | 
						|
%  format("Y ~d~n",[Y]),
 | 
						|
  update_QT_Y(T,Q_t_Y_par,QG,S,Q_t_Y_par1),
 | 
						|
  update_array(qt,Y,Q_t_Y_par1),
 | 
						|
  Y1 is Y+1,
 | 
						|
  update_QT(Y1,NEx,T,TQG,S).
 | 
						|
 | 
						|
update_QT_Y([],Q_t_Y_par,[],_S,Q_t_Y_par):-!.
 | 
						|
 | 
						|
update_QT_Y([HT|TT],Q_t_Y_par,[HQG|TQG],S,Q_t_Y_par1):-
 | 
						|
  rb_lookup(HT,Pr,Q_t_Y_par),
 | 
						|
  times(S,HQG,Delta),
 | 
						|
    sum_lower([1-Pr,Pr],Delta,Dist1),
 | 
						|
  normalize(Dist1,[_,Pr1]),
 | 
						|
%  format("t=~p Dist ~p ~f~n",[HT,Dist1,Pr1]),
 | 
						|
  rb_update(Q_t_Y_par,HT,Pr1,Q_t_Y_par2),
 | 
						|
  update_QT_Y(TT,Q_t_Y_par2,TQG,S,Q_t_Y_par1).
 | 
						|
 | 
						|
 | 
						|
/* sum the values of Q(ch|y) with the values of the step vector \delta
 | 
						|
*/
 | 
						|
sum_lower([],[],[]):-!.  
 | 
						|
 | 
						|
sum_lower([H0|T0],[H1|T1],[H3|T2]):-
 | 
						|
  (H1 < +inf->
 | 
						|
    H2 is H0+H1,
 | 
						|
    (H2<0.0001->
 | 
						|
      H3=0.0001
 | 
						|
    ;
 | 
						|
      H3=H2
 | 
						|
    )
 | 
						|
  ;
 | 
						|
    format("overflow",[]),
 | 
						|
    H3=H0+100
 | 
						|
  ),
 | 
						|
  sum_lower(T0,T1,T2).  
 | 
						|
 | 
						|
/* normalizes a distribution
 | 
						|
*/
 | 
						|
normalize(Dist1,Dist2):-
 | 
						|
  sum_list(Dist1,Sum),
 | 
						|
  (Sum=:=0.0->format("0 Sum",[])
 | 
						|
  ;
 | 
						|
    true
 | 
						|
  ),
 | 
						|
  divide(Sum,Dist1,Dist2).
 | 
						|
 | 
						|
/* compute the step size 
 | 
						|
*/
 | 
						|
compute_step(QGrad,IGrad,QTGrad,ITGrad,LogSize,S):-
 | 
						|
  %format("CH grad~n",[]),
 | 
						|
  compute_step(QGrad,IGrad,0,0,Sum0),
 | 
						|
  %format("T grad~n",[]),
 | 
						|
  compute_step(QTGrad,ITGrad,0,Sum0,Sum),
 | 
						|
  setting(epsilon_fraction,EF),
 | 
						|
  %format("Sum ~f~n",[Sum]),
 | 
						|
  S is LogSize/EF/Sum.
 | 
						|
 | 
						|
compute_step([],[],_Y,S,S).
 | 
						|
 | 
						|
 | 
						|
compute_step([HQ|TQ],[HI|TI],Y,Sum,S):-
 | 
						|
  append(HQ,DQ),
 | 
						|
  append(HI,DI),
 | 
						|
  vec_times(DQ,DI,D),
 | 
						|
  %format("~p~n",[D]),
 | 
						|
  sum_list(D,SumY),
 | 
						|
  %format("Y ~d SumY ~f~n",[Y,SumY]),
 | 
						|
  Sum1 is Sum + SumY,
 | 
						|
  Y1 is Y+1,
 | 
						|
  compute_step(TQ,TI,Y1,Sum1,S).
 | 
						|
 | 
						|
/* computes Q(Ch)
 | 
						|
*/  
 | 
						|
compute_Q_ch([],Q_ch,Q_ch):-!.
 | 
						|
  
 | 
						|
compute_Q_ch([ch(N,S)|T],Q_ch0,Q_ch1):-
 | 
						|
  rule_by_num(N,_V,_NH,HL,_BL),!,
 | 
						|
  length(HL,L),
 | 
						|
  list0(0,L,P0),
 | 
						|
  ex(NEx),
 | 
						|
  compute_Q_ch_DB(0,NEx,ch(N,S),P0,P1),
 | 
						|
  rb_insert(Q_ch0,ch(N,S),P1,Q_ch2),
 | 
						|
  compute_Q_ch(T,Q_ch2,Q_ch1).
 | 
						|
 | 
						|
compute_Q_ch([ch(N,S)|T],Q_ch0,Q_ch1):-
 | 
						|
  rb_insert(Q_ch0,ch(N,S),1.0,Q_ch2),
 | 
						|
  compute_Q_ch(T,Q_ch2,Q_ch1).
 | 
						|
 | 
						|
 | 
						|
/* computes \sum_y Q(ch|y)Q(y) for all values ch of a single choice variable
 | 
						|
*/
 | 
						|
compute_Q_ch_DB(N,N,_CH,P,P):-!.
 | 
						|
 | 
						|
compute_Q_ch_DB(Y,NEx,CH,P0,P1):-
 | 
						|
  array_element(qy,Y,PY),
 | 
						|
  array_element(q,Y,Q_ch_par),
 | 
						|
  rb_lookup(CH,Par,Q_ch_par),
 | 
						|
  update_dist(P0,Par,PY,P2),
 | 
						|
  Y1 is Y+1,
 | 
						|
  compute_Q_ch_DB(Y1,NEx,CH,P2,P1).
 | 
						|
 | 
						|
/* computes Q(ch|y)Q(y) for all values ch of a single choice variable and sums
 | 
						|
the result to an accumulator
 | 
						|
*/
 | 
						|
update_dist([],[],_PY,[]):-!.
 | 
						|
 | 
						|
update_dist([HP0|P0],[HPar|Par],PY,[HP1|P1]):-
 | 
						|
  HP1 is HP0+HPar*PY,
 | 
						|
  update_dist(P0,Par,PY,P1).
 | 
						|
  
 | 
						|
/* computes Q(T)
 | 
						|
*/  
 | 
						|
compute_Q_t([],Q_t,Q_t):-!.
 | 
						|
  
 | 
						|
compute_Q_t([H|T],Q_t0,Q_t1):-
 | 
						|
  ex(NEx),
 | 
						|
  compute_Q_t_DB(0,NEx,H,0,P1),
 | 
						|
  rb_insert(Q_t0,H,P1,Q_t2),
 | 
						|
  compute_Q_t(T,Q_t2,Q_t1).
 | 
						|
 | 
						|
/* computes \sum_y Q(t|y)Q(y) for all values t of a single t variable
 | 
						|
*/
 | 
						|
compute_Q_t_DB(N,N,_T,P,P):-!.
 | 
						|
 | 
						|
compute_Q_t_DB(Y,NEx,T,P0,P1):-
 | 
						|
  array_element(qy,Y,PY),
 | 
						|
  array_element(qt,Y,Q_t_par),
 | 
						|
  rb_lookup(T,Par,Q_t_par),
 | 
						|
  P2 is P0+Par*PY,
 | 
						|
  Y1 is Y+1,
 | 
						|
  compute_Q_t_DB(Y1,NEx,T,P2,P1).
 | 
						|
 | 
						|
/* computes the components of the gradient of Q, i.e. the direction that 
 | 
						|
maximizes the Lagrangian, i.e.
 | 
						|
\frac{\partial G_{ch_i,y}(Q,\gamma)}{\partial Q(ch_{i}|y)}&=&
 | 
						|
-\frac{1}{Q(ch_{i}|y)}+\\
 | 
						|
&&Q(y)(1-Q(ch_{i}|y))(\frac{1-\gamma}{Q(ch_i)}+\\
 | 
						|
&&\gamma E_{Q(CH|ch_{i},y_0)}[\mathcal{D}(y,ch_{t(i,y)},ch_i)]
 | 
						|
for all Ch_i, all values ch_i and all y
 | 
						|
 | 
						|
Moreover, it computes the gradient of I
 | 
						|
\frac{\partial I_Q(CH;Y)}{\partial Q(ch_{i0}|y_0)}&=&-\frac{\partial E_Q[\log Q(CH_i)}{\partial Q(ch_{i0}|y_0)}+\frac{\partial E_Q[\log Q(CH_i|y_0)}{\partial Q(ch_{i0}|y_0)}=\\
 | 
						|
&&-Q(y_0)(\log Q(ch_{i0})+1)+Q(y_0)(\log Q(ch_{i0}|y_0)+1)=\\
 | 
						|
&&Q(y_0)(-\log Q(ch_{i0})-1+\log Q(ch_{i0}|y_0)+1)=\\
 | 
						|
&&Q(y_0)(\log Q(ch_{i0}|y_0)-\log Q(ch_{i0}))
 | 
						|
for all Ch_i, all values ch_i and all y
 | 
						|
*/
 | 
						|
compute_Q_gradient(NEx,NEx,_Gamma,_Delta,_Q_ch,_Q_t,_R,_NR,_CH,_PAX,_T,[],QGrad,QGrad,IGrad,IGrad,QTGrad,QTGrad,ITGrad,ITGrad):-!.
 | 
						|
/*
 | 
						|
  QTGrad=[H|_],
 | 
						|
  format("~p~n",[H]).
 | 
						|
*/
 | 
						|
compute_Q_gradient(Y,NEx,Gamma,Delta,Q_ch,Q_t,R,NR,CH,PAX,T,[D|DT],QGrad0,QGrad1,IGrad0,IGrad1,QTGrad0,QTGrad1,ITGrad0,ITGrad1):-
 | 
						|
  array_element(q,Y,Q_ch_Y_par),
 | 
						|
  array_element(qt,Y,Q_t_Y_par),
 | 
						|
  array_element(qy,Y,Q_Y),
 | 
						|
  cycle_CH(CH,Y,Gamma,Delta,Q_ch_Y_par,Q_Y,Q_ch,Q_t_Y_par,PAX,D,[],QGradY,[],IGradY),
 | 
						|
  append(QGrad0,[QGradY],QGrad2),
 | 
						|
  append(IGrad0,[IGradY],IGrad2),
 | 
						|
  rb_new(U0),
 | 
						|
  compute_U(R,NR,Y,Q_ch_Y_par,U0,U),
 | 
						|
  cycle_T(T,Y,Gamma,Delta,U,Q_ch_Y_par,Q_Y,Q_t,Q_t_Y_par,PAX,D,[],QTGradY,[],ITGradY),
 | 
						|
  append(QTGrad0,[QTGradY],QTGrad2),
 | 
						|
  append(ITGrad0,[ITGradY],ITGrad2),
 | 
						|
  Y1 is Y+1,
 | 
						|
  compute_Q_gradient(Y1,NEx,Gamma,Delta,Q_ch,Q_t,R,NR,CH,PAX,T,DT,QGrad2,QGrad1,IGrad2,IGrad1,QTGrad2,QTGrad1,ITGrad2,ITGrad1).
 | 
						|
 | 
						|
compute_U([],[],_Y,_Q_ch_Y_par,U,U).
 | 
						|
 | 
						|
compute_U([HR-Inst|TR],[NR|TNR],Y,Q_ch_Y_par,U0,U):-
 | 
						|
  compute_U_inst(Inst,HR,NR,Y,Q_ch_Y_par,[],UR),
 | 
						|
  rb_insert(U0,HR,UR,U1),
 | 
						|
  compute_U(TR,TNR,Y,Q_ch_Y_par,U1,U).
 | 
						|
  
 | 
						|
compute_U_inst([],_N,_NR,_Y,_Q_ch_Y_par,U,U).
 | 
						|
 | 
						|
compute_U_inst([S|TS],N,NR,Y,Q_ch_Y_par,U0,U):-
 | 
						|
  def_rule_by_num(N,Sub,_HL,BL),!,
 | 
						|
  match_subs(S,Sub),
 | 
						|
  (body_true_unseen(BL,_BL,Y,1)->
 | 
						|
    prob_body(BL,Y,1,PTB,_B),
 | 
						|
    rb_lookup(ch(N,S),Q_ch_y,Q_ch_Y_par),  
 | 
						|
    scan_ch(Q_ch_y,[1.0],NR,PTB,UCH),
 | 
						|
    append(U0,[ch(N,S)-UCH],U1)
 | 
						|
  ;
 | 
						|
    U1 = U0
 | 
						|
  ),
 | 
						|
  compute_U_inst(TS,N,NR,Y,Q_ch_Y_par,U1,U).
 | 
						|
 | 
						|
compute_U_inst([S|TS],N,NR,Y,Q_ch_Y_par,U0,U):-
 | 
						|
  rule_by_num(N,Sub,_NH,_HL,BL),
 | 
						|
  match_subs(S,Sub),
 | 
						|
  (body_true_unseen(BL,_BL,Y,1)->
 | 
						|
    prob_body(BL,Y,1,PTB,_B),
 | 
						|
    rb_lookup(ch(N,S),Q_ch_y,Q_ch_Y_par),  
 | 
						|
    array_element(p,N,d(Theta,_Val)),
 | 
						|
    scan_ch(Q_ch_y,Theta,NR,PTB,UCH),
 | 
						|
    append(U0,[ch(N,S)-UCH],U1)
 | 
						|
  ;
 | 
						|
    U1 = U0
 | 
						|
  ),
 | 
						|
  compute_U_inst(TS,N,NR,Y,Q_ch_Y_par,U1,U).
 | 
						|
 | 
						|
 | 
						|
scan_ch([],[],_NR,_PTB,[]).
 | 
						|
  
 | 
						|
scan_ch([Q_ch_yH|Q_ch_yT],[ThetaH|ThetaT],NR,PTB,[UCHH|UCHT]):-
 | 
						|
  UCHH is Q_ch_yH*PTB/NR*(1/ThetaH+1),
 | 
						|
  scan_ch(Q_ch_yT,ThetaT,NR,PTB,UCHT).
 | 
						|
  
 | 
						|
  
 | 
						|
 | 
						|
 | 
						|
 | 
						|
 | 
						|
/* Computes \mathcal{N}(r), the denominator of \theta_{ch_r|true} for all rules
 | 
						|
r
 | 
						|
i.e
 | 
						|
\sum_{s\in i(r)}\sum_y Q(y)bt(pa_{ch_s}[y]+\alpha(r,true)
 | 
						|
for all r
 | 
						|
*/
 | 
						|
compute_Nr([],[]):-!.
 | 
						|
 | 
						|
compute_Nr([N-_Inst|TR],[1.0|TNR]):-
 | 
						|
  def_rule_by_num(N,_S,_H,_B),!,
 | 
						|
  compute_Nr(TR,TNR).
 | 
						|
 | 
						|
compute_Nr([N-Inst|TR],[NR|TNR]):-
 | 
						|
  ex(NEx),
 | 
						|
  compute_Nr_R(0,NEx,N,Inst,0,NR),
 | 
						|
  compute_Nr(TR,TNR).
 | 
						|
 | 
						|
/* Computes \mathcal{N}(r), for a single rule r
 | 
						|
i.e
 | 
						|
\sum_{s\in i(r)}\sum_y Q(y)bt(pa_{ch_s}[y]+\alpha(r,true)
 | 
						|
*/
 | 
						|
compute_Nr_R(NEx,NEx,_N,_Inst,NR,NR):-!.
 | 
						|
 | 
						|
compute_Nr_R(Y,NEx,N,Inst,NR0,NR1):-
 | 
						|
  array_element(qy,Y,Q_Y),
 | 
						|
  find_true_inst_unseen(Inst,N,Y,TInst),
 | 
						|
  scan_inst(TInst,N,Y,0,PTB),
 | 
						|
  NR2 is NR0+PTB*Q_Y,
 | 
						|
  Y1 is Y + 1,
 | 
						|
  compute_Nr_R(Y1,NEx,N,Inst,NR2,NR1).
 | 
						|
 | 
						|
scan_inst([],_N,_Y,PTB,PTB).
 | 
						|
 | 
						|
scan_inst([S|TS],N,Y,PTB0,PTB):-
 | 
						|
  rule_by_num(N,Sub,_NH,_HL,BL),
 | 
						|
  match_subs(S,Sub),
 | 
						|
  prob_body(BL,Y,1,PTSB,_B),
 | 
						|
  PTB1 is PTB0+PTSB,
 | 
						|
  scan_inst(TS,N,Y,PTB1,PTB).
 | 
						|
  
 | 
						|
prob_body([],_Y,PTSB,PTSB,[]).
 | 
						|
 | 
						|
prob_body([\+ H|T],Y,PTSB0,PTSB,B1):-!,
 | 
						|
  functor(H,P,A0),
 | 
						|
  A is A0-1,
 | 
						|
  (unseen(P/A)->
 | 
						|
    H=..[P,_|Args],
 | 
						|
    H1=..[P|Args],
 | 
						|
    array_element(qt,Y,Q_t_Y_par),
 | 
						|
    rb_lookup(H1,Q_t_y,Q_t_Y_par),
 | 
						|
    PTSB1 is PTSB0*(1-Q_t_y),
 | 
						|
    B1=[\+ H1|B0]
 | 
						|
  ;
 | 
						|
    PTSB1=PTSB0,
 | 
						|
    B1=B0
 | 
						|
    
 | 
						|
  ),
 | 
						|
  prob_body(T,Y,PTSB1,PTSB,B0).
 | 
						|
 | 
						|
prob_body([H|T],Y,PTSB0,PTSB,B1):-
 | 
						|
  functor(H,P,A0),
 | 
						|
  A is A0-1,
 | 
						|
  (unseen(P/A)->
 | 
						|
    H=..[P,_|Args],
 | 
						|
    H1=..[P|Args],
 | 
						|
    array_element(qt,Y,Q_t_Y_par),
 | 
						|
    rb_lookup(H1,Q_t_y,Q_t_Y_par),
 | 
						|
    PTSB1 is PTSB0*Q_t_y,
 | 
						|
    B1=[H1|B0]
 | 
						|
  ;
 | 
						|
    PTSB1=PTSB0,
 | 
						|
    B1=B0
 | 
						|
  ),
 | 
						|
  prob_body(T,Y,PTSB1,PTSB,B0).
 | 
						|
 | 
						|
 | 
						|
/* computes \mathcal{D}(y_0,ch_{t(i,y_0)},ch_{i0}
 | 
						|
\frac{1}{\mathcal{N}(r(i))}\left (\sum_{k,k\in  t(i,y_0)}\frac{1}{\theta_{Hd_{r(i)}=ch_k|true}}\right )\left (\sum_{s\in t(i,y_0),ch_{i0}=ch_s}
 | 
						|
1\right )=\\
 | 
						|
\frac{1}{\mathcal{N}(r(i))}T(i,ch_{t(i,y_0)})N(i,ch_{t(i,y_0)},ch_{i0})
 | 
						|
for all values of y
 | 
						|
*/
 | 
						|
compute_D(NEx,NEx,_Rules,_NR,[]):-!.
 | 
						|
 | 
						|
compute_D(Y,NEx,Rules,NR,[DY|TDY]):-
 | 
						|
  compute_D_y(Rules,NR,Y,DY),
 | 
						|
  Y1 is Y+1,
 | 
						|
  compute_D(Y1,NEx,Rules,NR,TDY).
 | 
						|
 | 
						|
/* computes \mathcal{D}(y_0,ch_{t(i,y_0)},ch_{i0}
 | 
						|
for a single value of y
 | 
						|
*/
 | 
						|
compute_D_y([],[],_Y,[]):-!.
 | 
						|
 | 
						|
compute_D_y([N-_Inst|TR],[1.0|TNR],Y,[N-0|DY]):-
 | 
						|
  def_rule_by_num(N,_V,_HL,_BL),!,
 | 
						|
  compute_D_y(TR,TNR,Y,DY).
 | 
						|
 | 
						|
compute_D_y([N-Inst|TR],[NR|TNR],Y,[N-DYN|DY]):-
 | 
						|
  rule_by_num(N,_V,_NH,HL,_BL),
 | 
						|
  length(HL,L),
 | 
						|
  find_true_inst_unseen(Inst,N,Y,TInst),
 | 
						|
%  length(TInst,LI),
 | 
						|
%  format("N inst ~d~n",[LI]),
 | 
						|
  generate_combinations(TInst,Y,N,L,NR,[],[],DYN),!,
 | 
						|
  compute_D_y(TR,TNR,Y,DY).
 | 
						|
 | 
						|
/* computes \mathcal{D}(y_0,ch_{t(i,y_0)},ch_{i0}
 | 
						|
for a single combination of values for ch_{t(i,y_0)}
 | 
						|
*/
 | 
						|
compute_D_comb(L,L,_Y,_Values,_PD,[]):-!.
 | 
						|
 | 
						|
compute_D_comb(L0,L,Y,Values,PD,[DVec|TD]):-
 | 
						|
  L1 is L0+1,
 | 
						|
  findall(ch(N,S),member((ch(N,S)=L1),Values),List),
 | 
						|
  scan_subs_list(List,Y,PD,DVec),
 | 
						|
  compute_D_comb(L1,L,Y,Values,PD,TD).
 | 
						|
 | 
						|
scan_subs_list([],_Y,_PD,[]).
 | 
						|
 | 
						|
scan_subs_list([ch(N,S)|T],Y,PD,[(B,QT,D)|DVec0]):-
 | 
						|
  rule_by_num(N,Sub,_NH,_HL,BL),
 | 
						|
  match_subs(S,Sub),
 | 
						|
  prob_body(BL,Y,1,QT,B),
 | 
						|
  D is PD*QT,
 | 
						|
  scan_subs_list(T,Y,PD,DVec0).
 | 
						|
 | 
						|
 | 
						|
/* computes T(i,ch_{t(i,y_0)}=
 | 
						|
\sum_{k,k\in  t(i,y_0)}\frac{1}{\theta_{Hd_{r(i)}=ch_k|true}}
 | 
						|
for a single combination of values for ch_{t(i,y_0)}
 | 
						|
*/
 | 
						|
compute_T([],_Theta,T,T):-!.
 | 
						|
 | 
						|
compute_T([_=Val|TVal],ThetaR,T0,T1):-
 | 
						|
  nth(Val,ThetaR,Theta),
 | 
						|
  T2 is T0+1/Theta,
 | 
						|
  compute_T(TVal,ThetaR,T2,T1).
 | 
						|
  
 | 
						|
/* generates all combinations of values for ch_{t(i,y_0)}
 | 
						|
and computes \mathcal{D}(y_0,ch_{t(i,y_0)},ch_{i0}
 | 
						|
*/
 | 
						|
generate_combinations([],Y,N,L,NR,Values,DYN,[f(Values,D)|DYN]):-!,
 | 
						|
  array_element(p,N,d(ThetaR,_Val)),
 | 
						|
  compute_T(Values,ThetaR,0,T),
 | 
						|
  PD is 1/NR*T,
 | 
						|
  compute_D_comb(0,L,Y,Values,PD,D).
 | 
						|
  
 | 
						|
generate_combinations([S|TS],Y,N,L,NR,Values,DYN0,DYN1):-
 | 
						|
  cycle_values(0,L,Y,N,S,TS,NR,Values,DYN0,DYN1).
 | 
						|
 | 
						|
/* auxiliary predicate for generating all combinations of values for 
 | 
						|
ch_{t(i,y_0)}
 | 
						|
*/  
 | 
						|
cycle_values(L,L,_Y,_N,_S,_TS,_NR,_Values,DYN,DYN):-!.
 | 
						|
  
 | 
						|
cycle_values(V,L,Y,N,S,TS,NR,Values,DYN0,DYN1):-
 | 
						|
  V1 is V+1,
 | 
						|
  generate_combinations(TS,Y,N,L,NR,[ch(N,S)=V1|Values],DYN0,DYN2),
 | 
						|
  cycle_values(V1,L,Y,N,S,TS,NR,Values,DYN2,DYN1).
 | 
						|
  
 | 
						|
/* finds the rule instances that have the body true */
 | 
						|
find_true_inst([],_N,_Ex,[]):-!.
 | 
						|
 | 
						|
find_true_inst([S|TS],N,Ex,[S|TInst]):-
 | 
						|
  rule_by_num(N,Sub,_NH,_HL,BL),
 | 
						|
  match_subs(S,Sub),
 | 
						|
  body_true(BL,Ex,1),!,
 | 
						|
  find_true_inst(TS,N,Ex,TInst).
 | 
						|
 | 
						|
find_true_inst([_S|TS],N,Ex,TInst):-
 | 
						|
  find_true_inst(TS,N,Ex,TInst).
 | 
						|
 | 
						|
find_true_inst_unseen([],_N,_Ex,[]):-!.
 | 
						|
 | 
						|
find_true_inst_unseen([S|TS],N,Ex,[S|TInst]):-
 | 
						|
  rule_by_num(N,Sub,_NH,_HL,BL),
 | 
						|
  match_subs(S,Sub),
 | 
						|
  body_true_unseen(BL,_BL,Ex,1),!,
 | 
						|
  find_true_inst_unseen(TS,N,Ex,TInst).
 | 
						|
 | 
						|
find_true_inst_unseen([_S|TS],N,Ex,TInst):-
 | 
						|
  find_true_inst_unseen(TS,N,Ex,TInst).
 | 
						|
 | 
						|
/* cycles over all the choice variables for computing the gradient
 | 
						|
\frac{\partial G_{ch_i,y}(Q,\gamma)}{\partial Q(ch_{i}|y)}
 | 
						|
*/
 | 
						|
cycle_CH([],_Y,_Gamma,_Delta,_Q_ch_Y_par,_Q_Y,_Q_ch_par,_Q_t_Y_par,_PAX,_D,QGrad,QGrad,IGrad,IGrad):-!.
 | 
						|
 | 
						|
cycle_CH([ch(N,_S)|T],Y,Gamma,Delta,Q_ch_Y_par,Q_Y,Q_ch_par,Q_t_Y_par,PAX,D,QGrad0,QGrad1,IGrad0,IGrad1):-
 | 
						|
  def_rule_by_num(N,_V,_HL,_BL),!,
 | 
						|
  cycle_CH(T,Y,Gamma,Delta,Q_ch_Y_par,Q_Y,Q_ch_par,Q_t_Y_par,PAX,D,QGrad0,QGrad1,IGrad0,IGrad1).
 | 
						|
 | 
						|
 | 
						|
cycle_CH([ch(N,S)|T],Y,Gamma,Delta,Q_ch_Y_par,Q_Y,Q_ch_par,Q_t_Y_par,PAX,D,QGrad0,QGrad1,IGrad0,IGrad1):-
 | 
						|
  rule_by_num(N,S,_NH,HL,BL),
 | 
						|
  get_atoms_head(HL,Val),
 | 
						|
  rb_lookup(ch(N,S),Q_ch_y,Q_ch_Y_par),
 | 
						|
  rb_lookup(ch(N,S),Q_ch,Q_ch_par),
 | 
						|
  compute_E_log_Q_ch(Q_ch_y,Q_ch,0,E_log_Q_ch), %ok
 | 
						|
  body_true_unseen(BL,_B,Y,BodyTrue),!,
 | 
						|
  prob_body(BL,Y,1,PTB,_B1),
 | 
						|
  array_element(p,N,d(Theta,_Val)),
 | 
						|
  compute_R(Val,ch(N,S),1,Y,PAX,Q_ch_Y_par,Q_t_Y_par,0,[],R), % ok
 | 
						|
  compute_EP(Val,Q_ch_y,Theta,BodyTrue,PTB,Q_t_Y_par,Y,EP,R,Delta,0,EEP),
 | 
						|
  member((N-DN),D),!,
 | 
						|
  length(HL,NVal),
 | 
						|
  list0(0,NVal,ED0),
 | 
						|
  compute_ED(DN,S,Q_ch_Y_par,ED0,ED),
 | 
						|
  cycle_CH_values(Q_ch_y,Q_ch,Q_Y,E_log_Q_ch,Gamma,EP,EEP,ED,D_ch_y,DI_ch_y),
 | 
						|
  append(QGrad0,[D_ch_y],QGrad2),
 | 
						|
  append(IGrad0,[DI_ch_y],IGrad2),
 | 
						|
  cycle_CH(T,Y,Gamma,Delta,Q_ch_Y_par,Q_Y,Q_ch_par,Q_t_Y_par,PAX,D,QGrad2,QGrad1,IGrad2,IGrad1).
 | 
						|
 | 
						|
/* cycles over all the values of a choice variable for computing the gradient
 | 
						|
\frac{\partial G_{ch_i,y}(Q,\gamma)}{\partial Q(ch_{i}|y)}
 | 
						|
*/
 | 
						|
cycle_CH_values([],[],_Q_y,_E_log_Q_ch,_Gamma,[],_EEP,[],[],[]):-!.
 | 
						|
 | 
						|
cycle_CH_values([Q_ch_y|TQ_ch_y],[Q_ch|TQ_ch],Q_y,E_log_Q_ch,Gamma,[EP|TEP],EEP,[ED|TED],
 | 
						|
  [Dir|D],[D_I|I]):-
 | 
						|
  D_Q is -1/Q_ch_y+Q_y*(1-Q_ch_y)*((1-Gamma)/Q_ch+Gamma*ED),
 | 
						|
  D_G is -log(Q_ch)+EP-EEP+E_log_Q_ch,
 | 
						|
  Dir is -D_G/D_Q,
 | 
						|
  ((Q_ch_y<1e-20;Q_ch<1e-20;abs(D_Q)<1e-10;abs(Dir)> 1e10)->
 | 
						|
    format("~f ~f ~f~n",[Q_ch_y,Q_ch,Dir])
 | 
						|
  ;
 | 
						|
    true
 | 
						|
  ),
 | 
						|
  D_I is Q_y*(log(Q_ch_y)-log(Q_ch)),
 | 
						|
  cycle_CH_values(TQ_ch_y,TQ_ch,Q_y,E_log_Q_ch,Gamma,TEP,EEP,TED,D,I).
 | 
						|
 | 
						|
cycle_T([],_Y,_Gamma,_Delta,_U,_Q_ch_Y_par,_Q_Y,_Q_t_par,_Q_t_Y_par,_PAX,_D,QGrad,QGrad,IGrad,IGrad):-!.
 | 
						|
 | 
						|
cycle_T([TH|T],Y,Gamma,Delta,U,Q_ch_Y_par,Q_Y,Q_t_par,Q_t_Y_par,PAX,D,QGrad0,QGrad1,IGrad0,IGrad1):-
 | 
						|
  rb_lookup(TH,Q_t_y,Q_t_Y_par),
 | 
						|
  rb_lookup(TH,Q_t,Q_t_par),
 | 
						|
  ((Q_t=<0;Q_t>1)->format("Q_t ~d ~p ~f~n",[Y,TH,Q_t]);true),
 | 
						|
  ((Q_t_y=<0;Q_t_y>1)->format("Q_t_y ~d ~p ~f~n",[Y,TH,Q_t_y]);true),
 | 
						|
  Exp_log_Q_T is (1-Q_t_y)*log(1-Q_t)+Q_t_y*log(Q_t),
 | 
						|
  TH=..[F|Args],
 | 
						|
  TH1=..[F,_|Args],
 | 
						|
  find_rules_with_T_in_the_body(TH,RT),
 | 
						|
  rb_lookup(TH,Pa_Th,PAX),
 | 
						|
  compute_EPT(RT,TH1,Pa_Th,Q_ch_Y_par,Q_t_y,Y,Delta,0,0,EPt,EPf),
 | 
						|
  Exp_Q_EP is (1-Q_t_y)*EPf+Q_t_y*EPt,
 | 
						|
  compute_EF(RT,TH1,Y,U,Q_ch_Y_par,Q_t_y,Q_Y,0,0,EFt,EFf),
 | 
						|
  D_Qf is -1/(1-Q_t_y)+(1-Q_t)*Q_t_y*((1-Gamma)/(1-Q_t)+Gamma*EFf),
 | 
						|
  D_Gf is -log(1-Q_t)+EPf-Exp_Q_EP+Exp_log_Q_T,
 | 
						|
  Dirf is -D_Gf/D_Qf,
 | 
						|
  D_Qt is -1/Q_t_y+Q_t*(1-Q_t_y)*((1-Gamma)/Q_t+Gamma*EFt),
 | 
						|
  D_Gt is -log(Q_t)+EPt-Exp_Q_EP+Exp_log_Q_T,
 | 
						|
  Dirt is -D_Gt/D_Qt,
 | 
						|
  DirIf is Q_Y*(log(1-Q_t_y)-log(1-Q_t)),
 | 
						|
  DirIt is  Q_Y*(log(Q_t_y)-log(Q_t)),
 | 
						|
  append(QGrad0,[[Dirf,Dirt]],QGrad2),
 | 
						|
  append(IGrad0,[[DirIf,DirIt]],IGrad2),
 | 
						|
  cycle_T(T,Y,Gamma,Delta,U,Q_ch_Y_par,Q_Y,Q_t_par,Q_t_Y_par,PAX,D,QGrad2,QGrad1,IGrad2,IGrad1).
 | 
						|
 | 
						|
find_rules_with_T_in_the_body(TH,RT):-
 | 
						|
  my_get_value(tch,TCh),
 | 
						|
  rb_lookup(TH,RT,TCh).
 | 
						|
 | 
						|
compute_EF([],_T,_Y,_U,_Q_ch_Y_par,Q_t_y,Q_y,EFt0,EFf0,EFt,EFf):-
 | 
						|
  EFt is EFt0*Q_y/Q_t_y,
 | 
						|
  EFf is EFf0*Q_y/(1-Q_t_y).
 | 
						|
  
 | 
						|
compute_EF([ch(N,S)|TR],T,Y,U,Q_ch_Y_par,Q_t_y,Q_y,EFt0,EFf0,EFt,EFf):-
 | 
						|
  def_rule_by_num(N,S1,_HL,BL),!,
 | 
						|
  match_subs(S,S1),
 | 
						|
  prob_body(BL,Y,1,PTB,_BT),
 | 
						|
  rb_lookup(ch(N,S),Q_ch_y,Q_ch_Y_par),
 | 
						|
  find_U_N(U,N,UN),
 | 
						|
  scan_UN(UN,Q_ch_y,0,0,SumUt,SumUf),
 | 
						|
  (member(T,BL)->
 | 
						|
    PTB1 is PTB/Q_t_y,
 | 
						|
    EFt1 is PTB1*SumUt+EFt0,
 | 
						|
    EFf1 = EFf0
 | 
						|
  ;
 | 
						|
    PTB1 is PTB/(1-Q_t_y),
 | 
						|
    EFf1 is PTB1*SumUf+EFf0,
 | 
						|
    EFt1 = EFt0
 | 
						|
  ),
 | 
						|
  compute_EF(TR,T,Y,U,Q_ch_Y_par,Q_t_y,Q_y,EFt1,EFf1,EFt,EFf).
 | 
						|
 | 
						|
 | 
						|
compute_EF([ch(N,S)|TR],T,Y,U,Q_ch_Y_par,Q_t_y,Q_y,EFt0,EFf0,EFt,EFf):-
 | 
						|
  rule_by_num(N,S1,_NH,_HL,BL),
 | 
						|
  match_subs(S,S1),
 | 
						|
  prob_body(BL,Y,1,PTB,_BT),
 | 
						|
  rb_lookup(ch(N,S),Q_ch_y,Q_ch_Y_par),
 | 
						|
  find_U_N(U,N,UN),
 | 
						|
  scan_UN(UN,Q_ch_y,0,0,SumUt,SumUf),
 | 
						|
  (member(T,BL)->
 | 
						|
    PTB1 is PTB/Q_t_y,
 | 
						|
    EFt1 is PTB1*SumUt+EFt0,
 | 
						|
    EFf1 = EFf0
 | 
						|
  ;
 | 
						|
    PTB1 is PTB/(1-Q_t_y),
 | 
						|
    EFf1 is PTB1*SumUf+EFf0,
 | 
						|
    EFt1 = EFt0
 | 
						|
  ),
 | 
						|
  compute_EF(TR,T,Y,U,Q_ch_Y_par,Q_t_y,Q_y,EFt1,EFf1,EFt,EFf).
 | 
						|
 | 
						|
find_U_N(U,N,UN):-
 | 
						|
  rb_lookup(N,UN,U).
 | 
						|
  
 | 
						|
scan_UN([],_Q_ch_y,SumUt,SumUf,SumUt,SumUf).
 | 
						|
 | 
						|
scan_UN([ch(N,S)-U|UT],Q_ch_y,SumUt0,SumUf0,SumUt,SumUf):-
 | 
						|
  def_rule_by_num(N,S1,_HL,BL),!,
 | 
						|
  match_subs(S,S1),
 | 
						|
  (member(T,BL)->
 | 
						|
    vec_times(U,Q_ch_y,L),
 | 
						|
    sum_list(L,Sum),
 | 
						|
    SumUt1 is SumUt0+Sum,
 | 
						|
    SumUf1 =SumUf0
 | 
						|
  ;
 | 
						|
    (member(\+ T,BL)->
 | 
						|
      vec_times(U,Q_ch_y,L),
 | 
						|
      sum_list(L,Sum),
 | 
						|
      SumUf1 is SumUt0+Sum,
 | 
						|
      SumUt1 =SumUt0
 | 
						|
    ;
 | 
						|
      SumUt1 =SumUt0,
 | 
						|
      SumUf1 =SumUf0
 | 
						|
    )
 | 
						|
  ),
 | 
						|
  scan_UN(UT,Q_ch_y,SumUt1,SumUf1,SumUt,SumUf).
 | 
						|
 | 
						|
scan_UN([ch(N,S)-U|UT],Q_ch_y,SumUt0,SumUf0,SumUt,SumUf):-
 | 
						|
  rule_by_num(N,S1,_NH,_HL,BL),
 | 
						|
  match_subs(S,S1),
 | 
						|
  (member(T,BL)->
 | 
						|
    vec_times(U,Q_ch_y,L),
 | 
						|
    sum_list(L,Sum),
 | 
						|
    SumUt1 is SumUt0+Sum,
 | 
						|
    SumUf1 =SumUf0
 | 
						|
  ;
 | 
						|
    (member(\+ T,BL)->
 | 
						|
      vec_times(U,Q_ch_y,L),
 | 
						|
      sum_list(L,Sum),
 | 
						|
      SumUf1 is SumUt0+Sum,
 | 
						|
      SumUt1 =SumUt0
 | 
						|
    ;
 | 
						|
      SumUt1 =SumUt0,
 | 
						|
      SumUf1 =SumUf0
 | 
						|
    )
 | 
						|
  ),
 | 
						|
  scan_UN(UT,Q_ch_y,SumUt1,SumUf1,SumUt,SumUf).
 | 
						|
 | 
						|
compute_EPT([],T,Pa_T,Q_ch_Y_par,_Q_t_Y,_Y,Delta,EPt0,EPf0,EPt,EPf):-
 | 
						|
  compute_prod_Pa_T(Pa_T,T,Q_ch_Y_par,1,Prod),
 | 
						|
  EPt is EPt0+Prod*Delta,
 | 
						|
  EPf is EPf0+(1-Prod)*Delta.
 | 
						|
 | 
						|
compute_EPT([ch(N,S)|TCH],T,Pa_T,Q_ch_Y_par,Q_t_Y,Y,Delta,EPt0,EPf0,EPt,EPf):-
 | 
						|
  def_rule_by_num(N,S1,_HL,BL),!,
 | 
						|
  match_subs(S,S1),
 | 
						|
%  ((member(T,BL);member(\+ T,BL))->
 | 
						|
    body_true_unseen(BL,_B,Y,BodyTrue),!,
 | 
						|
    (BodyTrue=:=1->
 | 
						|
      prob_body(BL,Y,1,PTB,_BT),
 | 
						|
      (member(T,BL)->
 | 
						|
        PTB_dif_T is PTB/Q_t_Y,
 | 
						|
        EPf1 is Delta,
 | 
						|
        EPt1 is 1-PTB_dif_T
 | 
						|
      ;
 | 
						|
        PTB_dif_T is PTB/(1-Q_t_Y),
 | 
						|
        EPf1 is 1-PTB_dif_T,
 | 
						|
        EPt1 is Delta
 | 
						|
      )
 | 
						|
    ;
 | 
						|
      (member(T,BL)->
 | 
						|
        EPf1 = 0,
 | 
						|
        EPt1 is Delta
 | 
						|
      ;
 | 
						|
        EPf1 is EPf1+Delta,
 | 
						|
        EPt1 is 0
 | 
						|
      )
 | 
						|
    )
 | 
						|
%  ;
 | 
						|
%    EPf1=0,
 | 
						|
%    EPt1=0
 | 
						|
%  )
 | 
						|
  ,
 | 
						|
  EPf3 is EPf0+EPf1,
 | 
						|
  EPt3 is EPt0+EPt1,
 | 
						|
  compute_EPT(TCH,T,Pa_T,Q_ch_Y_par,Q_t_Y,Y,Delta,EPt3,EPf3,EPt,EPf).
 | 
						|
 | 
						|
 | 
						|
compute_EPT([ch(N,S)|TCH],T,Pa_T,Q_ch_Y_par,Q_t_Y,Y,Delta,EPt0,EPf0,EPt,EPf):-
 | 
						|
  rule_by_num(N,S1,_NH,HL,BL),
 | 
						|
  match_subs(S,S1),
 | 
						|
%  ((member(T,BL);member(\+ T,BL))->
 | 
						|
    body_true_unseen(BL,_B,Y,BodyTrue),!,
 | 
						|
    (BodyTrue=:=1->
 | 
						|
      prob_body(BL,Y,1,PTB,_BT),
 | 
						|
      rb_lookup(ch(N,S),Q_ch_y,Q_ch_Y_par),
 | 
						|
      array_element(p,N,d(Theta,_Val)),
 | 
						|
      cycle_EPT_CH_val(Theta,HL,Q_ch_y,0,Sum,Q_ch_null_y),
 | 
						|
      (member(T,BL)->
 | 
						|
        PTB_dif_T is PTB/Q_t_Y,
 | 
						|
        EPf1 is Delta*(1-Q_ch_null_y),
 | 
						|
        EPt1 is PTB_dif_T*Sum+Delta*(Q_ch_null_y*PTB_dif_T+(1-Q_ch_null_y)*(1-PTB_dif_T))
 | 
						|
      ;
 | 
						|
        PTB_dif_T is PTB/(1-Q_t_Y),
 | 
						|
        EPf1 is PTB_dif_T*Sum+Delta*(Q_ch_null_y*PTB_dif_T+(1-Q_ch_null_y)*(1-PTB_dif_T)),
 | 
						|
        EPt1 is Delta*(1-Q_ch_null_y)
 | 
						|
      )
 | 
						|
    ;
 | 
						|
      (member(T,BL)->
 | 
						|
        EPf1 = 0,
 | 
						|
        EPt1 is Delta*(1-Q_ch_null_y)
 | 
						|
      ;
 | 
						|
        EPf1 is EPf1+Delta*(1-Q_ch_null_y),
 | 
						|
        EPt1 is 0
 | 
						|
      )
 | 
						|
    )
 | 
						|
%  ;
 | 
						|
%    EPf1=0,
 | 
						|
%    EPt1=0
 | 
						|
%  )
 | 
						|
  ,
 | 
						|
  EPf3 is EPf0+EPf1,
 | 
						|
  EPt3 is EPt0+EPt1,
 | 
						|
  compute_EPT(TCH,T,Pa_T,Q_ch_Y_par,Q_t_Y,Y,Delta,EPt3,EPf3,EPt,EPf).
 | 
						|
 | 
						|
compute_prod_Pa_T([],_T,_Q_ch_Y_par,Prod,Prod).
 | 
						|
 | 
						|
compute_prod_Pa_T([ch(N,_S)|TCH],T,Q_ch_Y_par,Prod0,Prod):-
 | 
						|
  def_rule_by_num(N,_V,_HL,_BL),!,
 | 
						|
  compute_prod_Pa_T(TCH,T,Q_ch_Y_par,Prod0,Prod).
 | 
						|
 | 
						|
compute_prod_Pa_T([ch(N,S)|TCH],T,Q_ch_Y_par,Prod0,Prod):-
 | 
						|
  rb_lookup(ch(N,S),Prob,Q_ch_Y_par),
 | 
						|
  rule_by_num(N,S1,_NH,HL,_BL),
 | 
						|
  match_subs(S,S1),
 | 
						|
  generate_nth_pos(1, Pos, HL, (T:_P)),
 | 
						|
  nth(Pos,Prob,P),
 | 
						|
  Prod1 is Prod0*(1-P),
 | 
						|
  compute_prod_Pa_T(TCH,T,Q_ch_Y_par,Prod1,Prod).
 | 
						|
      
 | 
						|
cycle_EPT_CH_val([],[],[],S,S,0).
 | 
						|
 | 
						|
cycle_EPT_CH_val([_],['':_P],[Q_ch_null_y],S,S,Q_ch_null_y):-!.
 | 
						|
 | 
						|
cycle_EPT_CH_val([HTheta|TTheta],[_H:_P|T],[Q_ch_yH|Q_ch_yT],S0,S,Q_ch_null_y):-
 | 
						|
  S1 is S0+Q_ch_yH*log(HTheta),
 | 
						|
  cycle_EPT_CH_val(TTheta,T,Q_ch_yT,S1,S,Q_ch_null_y).
 | 
						|
  
 | 
						|
 | 
						|
/* given an annotated head as a list, return the list of atoms
 | 
						|
*/
 | 
						|
get_atoms_head([],[]):-!.
 | 
						|
 | 
						|
get_atoms_head(['':_P],['']):-!.
 | 
						|
 | 
						|
get_atoms_head([H:_P|T],[H1|T1]):-
 | 
						|
  H=..[P,_|Rest],
 | 
						|
  H1=..[P|Rest],
 | 
						|
  get_atoms_head(T,T1).
 | 
						|
 | 
						|
/* computes R(i,ch,y)&=&
 | 
						|
\sum_{j\in p(i),x_j[y]=true,ch_i\neq x_j[y]}\prod_{ch_s\in pa_{x_j},s\neq i}Q(ch_s\neq x_j[y]|y)
 | 
						|
for all i and all y
 | 
						|
*/
 | 
						|
compute_R([],_CH,_NH,_Y,_PAX,_Q_Y,_Q_t_y,RTot,R0,R):-!,
 | 
						|
  subt(R0,R,RTot).
 | 
						|
 | 
						|
compute_R([''],_CH,_NH,_Y,_PAX,_Q_Y,_Q_t_y,RTot,R0,R):-!,
 | 
						|
  append(R0,[0],R1),
 | 
						|
  subt(R1,R,RTot).
 | 
						|
 | 
						|
compute_R([Val|T],CH,NH,Y,PAX,Q_Y,Q_t_y,RTot0,R0,R):-
 | 
						|
/*  rule_by_num(N,Sub,_NH,_HL,BL),
 | 
						|
  match_subs(S,Sub),
 | 
						|
  prob_body(BL,Y,1,PTSB,_B),*/
 | 
						|
  Val=..[F|Arg],
 | 
						|
  X=..[F,Y|Arg],
 | 
						|
  X1=..[F,_Y|Arg],
 | 
						|
  functor(Val,P,A),
 | 
						|
  (unseen(P/A)->
 | 
						|
    rb_lookup(Val,PAVal,PAX),
 | 
						|
    delete(PAVal,CH,PAVal1),
 | 
						|
    compute_R_x(PAVal1,X1,Q_Y,1,Prod0),
 | 
						|
    rb_lookup(Val,Pr_t,Q_t_y),
 | 
						|
    Prod is Prod0*Pr_t,
 | 
						|
    RTot2 is RTot0+Prod,
 | 
						|
    append(R0,[Prod],R1)  
 | 
						|
  ;
 | 
						|
    (call(X)->
 | 
						|
      rb_lookup(Val,PAVal,PAX),
 | 
						|
      delete(PAVal,CH,PAVal1),
 | 
						|
      compute_R_x(PAVal1,X1,Q_Y,1,Prod),
 | 
						|
      RTot2 is RTot0+Prod,
 | 
						|
      append(R0,[Prod],R1)
 | 
						|
    ;
 | 
						|
      RTot2=RTot0,
 | 
						|
      append(R0,[0],R1)
 | 
						|
    )
 | 
						|
  ),
 | 
						|
  NH1 is NH+1,
 | 
						|
  compute_R(T,CH,NH1,Y,PAX,Q_Y,Q_t_y,RTot2,R1,R).
 | 
						|
 | 
						|
/* subt(L,L1,RT) subts from RT all the elements of list L obtaining L1 
 | 
						|
*/
 | 
						|
subt([],[],_RT):-!.
 | 
						|
 | 
						|
subt([H|T],[H1|T1],RT):-
 | 
						|
  H1 is RT-H,
 | 
						|
  subt(T,T1,RT).
 | 
						|
 | 
						|
/* computes R(i,ch,y)&=&
 | 
						|
\sum_{ch_i\neq x_j[y]}\prod_{ch_s\in pa_{x_j},s\neq i}Q(ch_s\neq x_j[y]|y)
 | 
						|
for a single value x_j
 | 
						|
*/
 | 
						|
compute_R_x([],_X,_Q_Y,Prod,Prod):-!.
 | 
						|
 | 
						|
compute_R_x([ch(N,S)|T],X,Q_Y,Prod0,Prod1):-
 | 
						|
  rb_lookup(ch(N,S),Prob,Q_Y),
 | 
						|
  rule_by_num(N,S,_NH,HL,_BL),
 | 
						|
  generate_nth_pos(1, Pos, HL, (X:_P)),
 | 
						|
%  nth(Pos,HL,(X:_P)),!,
 | 
						|
  nth(Pos,Prob,P),
 | 
						|
  Prod2 is Prod0*(1-P),
 | 
						|
  compute_R_x(T,X,Q_Y,Prod2,Prod1).
 | 
						|
 | 
						|
/*  body_true(Body,Ex,BT) sets BT to 1 if Body is true in Ex and to 0
 | 
						|
otherwise
 | 
						|
Body is a list of literals, each with the example argument 
 | 
						|
*/
 | 
						|
body_true([],_Ex,1):-!.
 | 
						|
 | 
						|
body_true([H|T],Ex,BT):-
 | 
						|
  (inference_ib:builtin(H)->
 | 
						|
    body_true(T,[H],Ex,BT)
 | 
						|
  ;
 | 
						|
    H=..[_P,Ex|_A],
 | 
						|
    (test([H|T])->
 | 
						|
      BT=1
 | 
						|
    ;
 | 
						|
      BT=0
 | 
						|
    )
 | 
						|
  ).
 | 
						|
 | 
						|
body_true([H|T],In,Ex,BT):-
 | 
						|
  (inference_ib:builtin(H)->
 | 
						|
    append(In,[H],In1),
 | 
						|
    body_true(T,In1,Ex,BT)
 | 
						|
  ;
 | 
						|
    H=..[_P,Ex|_A],
 | 
						|
    append(In,[H|T],B),
 | 
						|
    (test(B)->
 | 
						|
      BT=1
 | 
						|
    ;
 | 
						|
      BT=0
 | 
						|
    )
 | 
						|
  ).
 | 
						|
 | 
						|
body_true_unseen([],[],_Ex,1):-!.
 | 
						|
 | 
						|
body_true_unseen([\+ H|T],B,Ex,BT):-!,
 | 
						|
  (inference_ib:builtin(H)->
 | 
						|
    body_true_unseen(T,[\+ H],B,Ex,BT)
 | 
						|
  ;
 | 
						|
    H=..[_P,Ex|_A],
 | 
						|
    (test_unseen([\+ H|T],B)->
 | 
						|
      BT=1
 | 
						|
    ;
 | 
						|
      BT=0
 | 
						|
    )
 | 
						|
  ).
 | 
						|
  
 | 
						|
body_true_unseen([H|T],B,Ex,BT):-
 | 
						|
  (inference_ib:builtin(H)->
 | 
						|
    body_true_unseen(T,[ H],B,Ex,BT)
 | 
						|
  ;
 | 
						|
    H=..[_P,Ex|_A],
 | 
						|
    (test_unseen([H|T],B)->
 | 
						|
      BT=1
 | 
						|
    ;
 | 
						|
      BT=0
 | 
						|
    )
 | 
						|
  ).
 | 
						|
 | 
						|
body_true_unseen([\+ H|T],In,B,Ex,BT):-!,
 | 
						|
  (inference_ib:builtin(H)->
 | 
						|
    append(In,[\+ H],In1),
 | 
						|
    body_true_unseen(T,In1,B,Ex,BT)
 | 
						|
  ;
 | 
						|
    H=..[_P,Ex|_A],
 | 
						|
    append(In,[\+ H|T],BB),
 | 
						|
    (test_unseen(BB,B)->
 | 
						|
      BT=1
 | 
						|
    ;
 | 
						|
      BT=0
 | 
						|
    )
 | 
						|
  ).
 | 
						|
  
 | 
						|
body_true_unseen([H|T],In,B,Ex,BT):-
 | 
						|
  (inference_ib:builtin(H)->
 | 
						|
    append(In,[H],In1),
 | 
						|
    body_true_unseen(T,In1,B,Ex,BT)
 | 
						|
  ;
 | 
						|
    H=..[_P,Ex|_A],
 | 
						|
    append(In,[H|T],BB),
 | 
						|
    (test_unseen(BB,B)->
 | 
						|
      BT=1
 | 
						|
    ;
 | 
						|
      BT=0
 | 
						|
    )
 | 
						|
  ).
 | 
						|
  
 | 
						|
/* test(L) succeeds if L is true in the database
 | 
						|
*/  
 | 
						|
test([]).
 | 
						|
 | 
						|
test([H|T]):-
 | 
						|
  call(H),
 | 
						|
  test(T).      
 | 
						|
 | 
						|
test_unseen([],[]).
 | 
						|
 | 
						|
test_unseen([\+ H|Tail],B):-!,
 | 
						|
  functor(H,P,A0),
 | 
						|
  A is A0-1,
 | 
						|
  (unseen(P/A)->
 | 
						|
  /*  my_get_value(t,T),
 | 
						|
    H=..[P,_|Args],
 | 
						|
    H1=..[P|Args],
 | 
						|
    member(H1,T),*/
 | 
						|
    B=[\+ H|B1]
 | 
						|
  ;
 | 
						|
    call(\+ H),
 | 
						|
    B=B1
 | 
						|
  ),
 | 
						|
  test_unseen(Tail,B1).      
 | 
						|
 | 
						|
 | 
						|
test_unseen([H|Tail],B):-
 | 
						|
  functor(H,P,A0),
 | 
						|
  A is A0-1,
 | 
						|
  (unseen(P/A)->
 | 
						|
    my_get_value(t,T),
 | 
						|
    H=..[P,_|Args],
 | 
						|
    H1=..[P|Args],
 | 
						|
    member(H1,T),
 | 
						|
    B=[H|B1]
 | 
						|
  ;
 | 
						|
    call(H),
 | 
						|
    B=B1
 | 
						|
  ),
 | 
						|
  test_unseen(Tail,B1).      
 | 
						|
 | 
						|
/* computes E_{Q(CH|ch_{i},y_0)}[\mathcal{D}(y,ch_{t(i,y)},ch_i)]
 | 
						|
*/
 | 
						|
compute_ED([],_S,_Q_y_par,ED,ED):-!.
 | 
						|
 | 
						|
compute_ED([f(Values,D)|TD],S,Q_y_par,ED0,ED1):-
 | 
						|
  delete_matching(Values,(ch(_N,S)=_Val),Values1),!,
 | 
						|
  single_rules_ed_contrib(D,Term0),
 | 
						|
  compute_term(Values1,Q_y_par,Term0,Term),
 | 
						|
  sum(ED0,Term,ED2),
 | 
						|
  compute_ED(TD,S,Q_y_par,ED2,ED1).
 | 
						|
 | 
						|
/*
 | 
						|
delete_matching([],_El,[]):-!.
 | 
						|
 | 
						|
delete_matching([El|T],El,TR):-!,
 | 
						|
  delete_matching(T,El,TR).
 | 
						|
 | 
						|
delete_matching([H|T],El,[H|TR]):-!,
 | 
						|
  delete_matching(T,El,TR).
 | 
						|
*/
 | 
						|
 | 
						|
 | 
						|
/* computes Q(ch_j|y)\mathcal{D}(y,ch_{t(i,y)},ch_i) for all values ch_j of 
 | 
						|
Ch_j
 | 
						|
*/
 | 
						|
compute_term([],_Q_ch_y_par,Term,Term):-!.
 | 
						|
 | 
						|
compute_term([ch(N,S)=Val|TVal],Q_ch_y_par,Term0,Term1):-
 | 
						|
  rb_lookup(ch(N,S),Q_ch_y,Q_ch_y_par),
 | 
						|
  nth(Val,Q_ch_y,Q_ch_y_val),
 | 
						|
  times(Q_ch_y_val,Term0,Term2),
 | 
						|
  compute_term(TVal,Q_ch_y_par,Term2,Term1).
 | 
						|
 | 
						|
single_rules_ed_contrib([],[]).
 | 
						|
 | 
						|
single_rules_ed_contrib([H|T],[SR|TSR]):-
 | 
						|
  single_rules_ed_contrib_ch_val(H,0,SR),
 | 
						|
  single_rules_ed_contrib(T,TSR).
 | 
						|
  
 | 
						|
single_rules_ed_contrib_ch_val([],SR,SR).
 | 
						|
 | 
						|
single_rules_ed_contrib_ch_val([(_B,QT,D)|T],SR0,SR):-
 | 
						|
  SR1 is SR0+QT*D,
 | 
						|
  single_rules_ed_contrib_ch_val(T,SR1,SR).
 | 
						|
 | 
						|
/* sum(L1,L2,L) sums lists L1 and L2 element by element
 | 
						|
*/
 | 
						|
sum([],[],[]):-!.  
 | 
						|
 | 
						|
sum([H0|T0],[H1|T1],[H2|T2]):-
 | 
						|
  H2 is H0+H1,
 | 
						|
  sum(T0,T1,T2).  
 | 
						|
  
 | 
						|
/* vec_times(L1,L2,L) multiplies lists L1 and L2 element by element
 | 
						|
*/
 | 
						|
vec_times([],[],[]):-!.  
 | 
						|
 | 
						|
vec_times([H0|T0],[H1|T1],[H2|T2]):-
 | 
						|
  H2 is H0*H1,
 | 
						|
  vec_times(T0,T1,T2).  
 | 
						|
 | 
						|
/* computes 
 | 
						|
EP'(ch_i,y)
 | 
						|
&=&\\
 | 
						|
&&\log \theta_{Hd_{r(k)}=ch_i|pa_{ch_k}}[y]1\{body(pa_{ch_i})=true\}+\\
 | 
						|
&&\delta(\{body(pa_{ch_i})=false,ch_i\neq null\}+\\
 | 
						|
&&R(i,ch,y) +\\
 | 
						|
&&1\{ch_i\neq null,val(ch_i)[y]=false\})
 | 
						|
*/
 | 
						|
compute_EP([],[],[],_BodyTrue,_PTB,_Q_t_Y_par,_Ex,[],[],_Delta,EEP,EEP):-!.
 | 
						|
 | 
						|
compute_EP([''],[Prob_ch_y],[Theta],BodyTrue,PTB,_Q_t_Y_par,_Ex,[EP],[R],Delta,EEP0,EEP1):-!,
 | 
						|
  EP is log(Theta)*BodyTrue*PTB+Delta*R,
 | 
						|
  EEP1 is EEP0+EP*Prob_ch_y.
 | 
						|
 | 
						|
compute_EP([Val|TVal],[Prob_ch_y|TP],[Theta|TTheta],BodyTrue,PTB,Q_t_Y_par,Ex,[EP|TEP],[R|TR],Delta,EEP0,EEP1):-
 | 
						|
  Val=..[F|Args],
 | 
						|
  X=..[F,Ex|Args],
 | 
						|
  functor(Val,Pred,Arity),
 | 
						|
  (unseen(Pred/Arity)->
 | 
						|
    rb_lookup(Val,XPFalse,Q_t_Y_par),
 | 
						|
    XFalse is 1- XPFalse
 | 
						|
  ;
 | 
						|
    (call(X)->
 | 
						|
      XFalse=0
 | 
						|
    ;
 | 
						|
      XFalse=1
 | 
						|
    )
 | 
						|
  ),
 | 
						|
  EP is log(Theta)*BodyTrue*PTB+ Delta*((1-BodyTrue)+BodyTrue*(1-PTB)+R+XFalse),
 | 
						|
  EEP2 is EEP0+EP*Prob_ch_y,
 | 
						|
  compute_EP(TVal,TP,TTheta,BodyTrue,PTB,Q_t_Y_par,Ex,TEP,TR,Delta,EEP2,EEP1).
 | 
						|
 | 
						|
/* computes E_{Q(ch_i|y)}[\log Q(ch_i)]&=&\sum_{ch_i}Q(ch_i|y)\log Q(ch_i)
 | 
						|
*/  
 | 
						|
compute_E_log_Q_ch([],[],E,E):-!.
 | 
						|
 | 
						|
compute_E_log_Q_ch([HProb_ch_y|T],[Prob_ch|T1],E0,E1):-
 | 
						|
  E2 is E0+HProb_ch_y*log(Prob_ch),
 | 
						|
  compute_E_log_Q_ch(T,T1,E2,E1).
 | 
						|
 | 
						|
/* builds the initial Q table, with one entry for each example and each choice
 | 
						|
variable 
 | 
						|
q is an array with the example number as index
 | 
						|
*/
 | 
						|
build_q_table(CH):-
 | 
						|
    ex(NEx),
 | 
						|
  add_Q_par(0,NEx,CH).
 | 
						|
 | 
						|
/* cycles over the examples for building the Q table
 | 
						|
*/
 | 
						|
add_Q_par(N,N,_CH):-!.  
 | 
						|
 | 
						|
add_Q_par(N,NEx,CH):-
 | 
						|
  rb_new(Q_Y0),
 | 
						|
  add_Q_Y_par(CH,Q_Y0,Q_Y1),
 | 
						|
  update_array(q,N,Q_Y1),
 | 
						|
  N1 is N+1,
 | 
						|
  add_Q_par(N1,NEx,CH).
 | 
						|
 | 
						|
/* cycles over the choice variables and builds Q(ch|y) a rb_tree with ch(N,S) as key
 | 
						|
and the distribution in the form of a list of probabilities as value
 | 
						|
*/
 | 
						|
add_Q_Y_par([],Q,Q).  
 | 
						|
 | 
						|
add_Q_Y_par([ch(N,S)|T],Q0,Q1):-
 | 
						|
  def_rule_by_num(N,_V,_HL,_BL),!,
 | 
						|
  rb_insert(Q0,ch(N,S),[1.0],Q2),
 | 
						|
  add_Q_Y_par(T,Q2,Q1).
 | 
						|
 | 
						|
add_Q_Y_par([ch(N,S)|T],Q0,Q1):-
 | 
						|
  rule_by_num(N,_V,_NH,HL,_BL),
 | 
						|
  length(HL,NHL),
 | 
						|
  Prob is 1/NHL,
 | 
						|
  PertSize is Prob*0.1,
 | 
						|
  gen_random_param(NHL,0,PertSize,Prob,Par),
 | 
						|
  rb_insert(Q0,ch(N,S),Par,Q2),
 | 
						|
  add_Q_Y_par(T,Q2,Q1).
 | 
						|
  
 | 
						|
/* generates an initial random distribution for Q(ch|y)
 | 
						|
the distribution is obtained by randomly perturbing an uniform distribution
 | 
						|
*/
 | 
						|
gen_random_param(0,_Sum,_PertSize,_P,[]):-!.
 | 
						|
 | 
						|
gen_random_param(N,Sum,PertSize,P,[P1|Par]):-
 | 
						|
  TotMass is 1-Sum,
 | 
						|
  Mass is TotMass/N,
 | 
						|
  LowerBound is -PertSize,
 | 
						|
  random(LowerBound,PertSize,Pert),
 | 
						|
  P2 is Mass+Pert,
 | 
						|
  N1 is N-1,
 | 
						|
  Sum2 is Sum+P2,
 | 
						|
  (Sum2>1.0->
 | 
						|
    P1 = Mass,
 | 
						|
    Sum1 is Sum+Mass
 | 
						|
  ; 
 | 
						|
    P1 = P2,
 | 
						|
    Sum1 = Sum2    
 | 
						|
  ),
 | 
						|
  gen_random_param(N1,Sum1,PertSize,P,Par).
 | 
						|
 | 
						|
/* builds the initial Q(t|y) table, with one entry for each example and each T
 | 
						|
variable 
 | 
						|
q is an array with the example number as index
 | 
						|
*/
 | 
						|
build_qt_table(T):-
 | 
						|
    ex(NEx),
 | 
						|
  add_Qt_par(0,NEx,T).
 | 
						|
 | 
						|
/* cycles over the examples for building the Q(t|y) table
 | 
						|
*/
 | 
						|
add_Qt_par(N,N,_T):-!.  
 | 
						|
 | 
						|
add_Qt_par(N,NEx,T):-
 | 
						|
  rb_new(Q_Y0),
 | 
						|
  add_Qt_Y_par(T,Q_Y0,Q_Y1),
 | 
						|
  update_array(qt,N,Q_Y1),
 | 
						|
  N1 is N+1,
 | 
						|
  add_Qt_par(N1,NEx,T).
 | 
						|
 | 
						|
/* cycles over the T variables and builds Q(t|y) a rb_tree with t as key
 | 
						|
and the distribution in the form of a probability
 | 
						|
*/
 | 
						|
add_Qt_Y_par([],Q,Q).  
 | 
						|
 | 
						|
add_Qt_Y_par([H|T],Q0,Q1):-
 | 
						|
  random(Par),
 | 
						|
  rb_insert(Q0,H,Par,Q2),
 | 
						|
  add_Qt_Y_par(T,Q2,Q1).
 | 
						|
  
 | 
						|
 | 
						|
/* builds the p table with one entry for each example and each choice
 | 
						|
variable 
 | 
						|
p is an array with the rule number as index
 | 
						|
*/
 | 
						|
build_p_table(Rules):-
 | 
						|
  setting(max_rules,MR),
 | 
						|
%  length(Rules,N),
 | 
						|
  array(p,MR),
 | 
						|
  add_P_par(Rules).
 | 
						|
 | 
						|
/* retrieves the initial values of the theta vectore and stores it in the
 | 
						|
p array
 | 
						|
*/  
 | 
						|
add_P_par([]).  
 | 
						|
 | 
						|
add_P_par([def_rule(_N,_S,_H,_BL)|T]):-!,
 | 
						|
  add_P_par(T).
 | 
						|
 | 
						|
add_P_par([rule(N,_V,_NH,HL,_BL,_LogF)|T]):-
 | 
						|
  find_atoms_head(HL,Atoms,Probs),
 | 
						|
  update_array(p,N,d(Probs,Atoms)),
 | 
						|
  add_P_par(T).
 | 
						|
 | 
						|
/* builds the Bayesian network equivalent to the current model
 | 
						|
*/  
 | 
						|
build_network_IB(CH,PAX,T,TCh,R,LogSize):-
 | 
						|
  ex(NEx),
 | 
						|
  get_ouptut_atoms(O),
 | 
						|
  %rb_new(C0),
 | 
						|
  generate_ground1(0,NEx,O,[],L),
 | 
						|
  build_ground_lpad(L,CL),
 | 
						|
%  write(find_ground_atoms),nl,
 | 
						|
%  flush_output,
 | 
						|
  find_ground_atoms(CL,[],GAD0,[],GUAD0),
 | 
						|
  generate_goal_DB(0,NEx,O,[],GL),
 | 
						|
  get_atoms(GL,Atoms1),
 | 
						|
  append(GAD0,Atoms1,GAD),
 | 
						|
  remove_duplicates(GAD,X),
 | 
						|
%  write('X'),write(X),nl,
 | 
						|
  remove_duplicates(GUAD0,T),
 | 
						|
%  write('T'),write(T),nl,
 | 
						|
  rb_new(R0),
 | 
						|
  choice_vars_IB(CL,CH,0,LogSize0,R0,R1),
 | 
						|
  length(T,LST),
 | 
						|
  LogSize is LogSize0+LST,
 | 
						|
  rb_visit(R1,R),
 | 
						|
%  write('R'),write(R),nl,
 | 
						|
  rb_new(PAX0),
 | 
						|
  get_X_parents(CL,PAX0,PAX1),
 | 
						|
  add_parentless_X(X,PAX1,PAX),
 | 
						|
  rb_new(TCh0),
 | 
						|
  get_T_children(CL,TCh0,TCh1),
 | 
						|
  add_childless_T(T,TCh1,TCh).
 | 
						|
  
 | 
						|
find_ground_atoms([],GA,GA,GUA,GUA):-!.
 | 
						|
 | 
						|
find_ground_atoms([d(_N,_S,H,Body)|T],GA0,GA,GUA0,GUA):-!,
 | 
						|
  %write(fga),
 | 
						|
        H=..[F,_|R],
 | 
						|
  H1=..[F|R],
 | 
						|
  functor(H1,P,A),
 | 
						|
  (input_cw(P/A)->
 | 
						|
    find_atoms_body(T,GA0,GA,GUA0,GUA)
 | 
						|
  ;        
 | 
						|
    (unseen(P/A)->
 | 
						|
                  find_atoms_body(T,GA0,GA1,[H1|GUA0],GUA1)
 | 
						|
          ;
 | 
						|
                  find_atoms_body(T,[H1|GA0],GA1,GUA0,GUA1)
 | 
						|
          )
 | 
						|
  ),
 | 
						|
  find_atoms_body(Body,GA1,GA2,GUA1,GUA2),
 | 
						|
  find_ground_atoms(T,GA2,GA,GUA2,GUA).
 | 
						|
 | 
						|
find_ground_atoms([(_N,_S,Head,Body)|T],GA0,GA,GUA0,GUA):-
 | 
						|
  %write(fga),
 | 
						|
  find_atoms_head(Head,GA0,GA1,GUA0,GUA1),
 | 
						|
  find_atoms_body(Body,GA1,GA2,GUA1,GUA2),
 | 
						|
  find_ground_atoms(T,GA2,GA,GUA2,GUA).
 | 
						|
 | 
						|
find_atoms_body([],GA,GA,GUA,GUA):-!.
 | 
						|
 | 
						|
find_atoms_body([\+H|T],GA0,GA,GUA0,GUA):-
 | 
						|
  inference_ib:builtin(H),!,
 | 
						|
  find_atoms_body(T,GA0,GA,GUA0,GUA).
 | 
						|
 | 
						|
find_atoms_body([H|T],GA0,GA,GUA0,GUA):-
 | 
						|
  inference_ib:builtin(H),!,
 | 
						|
  find_atoms_body(T,GA0,GA,GUA0,GUA).
 | 
						|
 | 
						|
 | 
						|
find_atoms_body([\+H|T],GA0,GA,GUA0,GUA):-!,
 | 
						|
  H=..[F,_|R],
 | 
						|
  H1=..[F|R],
 | 
						|
  functor(H1,P,A),
 | 
						|
  (unseen(P/A)->
 | 
						|
    find_atoms_body(T,GA0,GA,[H1|GUA0],GUA)
 | 
						|
  ;
 | 
						|
    find_atoms_body(T,[H1|GA0],GA,GUA0,GUA)
 | 
						|
  ).
 | 
						|
 | 
						|
find_atoms_body([H|T],GA0,GA,GUA0,GUA):-!,
 | 
						|
  H=..[F,_|R],
 | 
						|
  H1=..[F|R],
 | 
						|
  functor(H1,P,A),
 | 
						|
  (unseen(P/A)->
 | 
						|
    find_atoms_body(T,GA0,GA,[H1|GUA0],GUA)
 | 
						|
  ;
 | 
						|
    find_atoms_body(T,[H1|GA0],GA,GUA0,GUA)
 | 
						|
  ).
 | 
						|
 | 
						|
find_atoms_head([],GA,GA,GUA,GUA).
 | 
						|
 | 
						|
find_atoms_head(['':_P],GA,GA,GUA,GUA):-!.
 | 
						|
 | 
						|
find_atoms_head([H:_P|T],GA0,GA,GUA0,GUA):-
 | 
						|
  H=..[F,_|R],
 | 
						|
  H1=..[F|R],
 | 
						|
  functor(H1,P,A),
 | 
						|
  (unseen(P/A)->
 | 
						|
    find_atoms_head(T,GA0,GA,[H1|GUA0],GUA)
 | 
						|
  ;
 | 
						|
    find_atoms_head(T,[H1|GA0],GA,GUA0,GUA)
 | 
						|
  ).
 | 
						|
 | 
						|
get_T_children([],TCh,TCh):-!.
 | 
						|
 | 
						|
get_T_children([d(N,S,_Head,Body)|T],TCh0,TCh):-!,
 | 
						|
  scan_body_for_T(Body,N,S,TCh0,TCh1),
 | 
						|
  get_T_children(T,TCh1,TCh).
 | 
						|
 | 
						|
get_T_children([(N,S,_Head,Body)|T],TCh0,TCh):-
 | 
						|
  scan_body_for_T(Body,N,S,TCh0,TCh1),
 | 
						|
  get_T_children(T,TCh1,TCh).
 | 
						|
 | 
						|
/* collects the atoms in the head of the rule corresponding to ch(M,S)
 | 
						|
*/
 | 
						|
scan_body_for_T([],_N,_S,TCh,TCh):-!.
 | 
						|
 | 
						|
scan_body_for_T([\+ H|T],N,S,TCh0,TCh):-!,
 | 
						|
  H=..[F,_|R],
 | 
						|
  H1=..[F|R],
 | 
						|
  functor(H1,P,A),
 | 
						|
  (unseen(P/A)->
 | 
						|
    (rb_lookup(H,Ch,TCh0)->
 | 
						|
      rb_update(TCh0,H,[ch(N,S)|Ch],TCh1)
 | 
						|
    ;
 | 
						|
      rb_insert(TCh0,H,[ch(N,S)],TCh1)
 | 
						|
    )
 | 
						|
  ;
 | 
						|
    TCh1=TCh0
 | 
						|
  ),
 | 
						|
  scan_body_for_T(T,N,S,TCh1,TCh).
 | 
						|
 | 
						|
scan_body_for_T([H|T],N,S,TCh0,TCh):-  
 | 
						|
  H=..[F,_|R],
 | 
						|
  H1=..[F|R],
 | 
						|
  (rb_lookup(H1,Ch,TCh0)->
 | 
						|
    rb_update(TCh0,H1,[ch(N,S)|Ch],TCh1)
 | 
						|
  ;
 | 
						|
    rb_insert(TCh0,H1,[ch(N,S)],TCh1)
 | 
						|
  ),
 | 
						|
  scan_body_for_T(T,N,S,TCh1,TCh).
 | 
						|
  
 | 
						|
get_X_parents([],_CL,PAX,PAX):-!.
 | 
						|
 | 
						|
get_X_parents([X|TX],CL,PAX0,PAX1):-
 | 
						|
  X=..[F|Args],
 | 
						|
  X1=..[F,_Y|Args],
 | 
						|
  findall(ch(N,S),
 | 
						|
  (
 | 
						|
    member((N,S,Head,_Body),CL),member((X1:_P),Head)
 | 
						|
    ;
 | 
						|
    member(d(N,S,X1,_Body),CL)
 | 
						|
  ),
 | 
						|
    PAX),
 | 
						|
  rb_insert(PAX0,X,PAX,PAX2),
 | 
						|
  get_X_parents(TX,CL,PAX2,PAX1).
 | 
						|
 | 
						|
add_parentless_X([],PAX,PAX).
 | 
						|
 | 
						|
add_parentless_X([X|T],PAX0,PAX1):-
 | 
						|
  (rb_lookup(X,_PA,PAX0)->
 | 
						|
    PAX2=PAX0
 | 
						|
  ;
 | 
						|
    rb_insert(PAX0,X,[],PAX2)
 | 
						|
  ),
 | 
						|
  add_parentless_X(T,PAX2,PAX1).
 | 
						|
 | 
						|
add_childless_T([],TCh,TCh).
 | 
						|
 | 
						|
add_childless_T([T|TT],TCh0,TCh):-
 | 
						|
  (rb_lookup(T,_Children,TCh0)->
 | 
						|
    TCh1=TCh0
 | 
						|
  ;
 | 
						|
    rb_insert(TCh0,T,[],TCh1)
 | 
						|
  ),
 | 
						|
  add_childless_T(TT,TCh1,TCh).
 | 
						|
 | 
						|
/* for each ground atoms, it finds the choice variables that are its parents
 | 
						|
for each grounding of a clause, it collects the atoms in the head
 | 
						|
*/
 | 
						|
get_X_parents([],PAX,PAX):-!.
 | 
						|
 | 
						|
get_X_parents([d(N,S,Head,_Body)|T],PAX0,PAX1):-
 | 
						|
  scan_head([Head:1.0],N,S,PAX0,PAX2),
 | 
						|
  get_X_parents(T,PAX2,PAX1).
 | 
						|
 | 
						|
 | 
						|
get_X_parents([(N,S,Head,_Body)|T],PAX0,PAX1):-
 | 
						|
  scan_head(Head,N,S,PAX0,PAX2),
 | 
						|
  get_X_parents(T,PAX2,PAX1).
 | 
						|
 | 
						|
/* collects the atoms in the head of the rule corresponding to ch(M,S)
 | 
						|
*/
 | 
						|
scan_head([],_N,_S,PAX,PAX).
 | 
						|
 | 
						|
scan_head(['':_P],_N,_S,PAX,PAX):-!.
 | 
						|
 | 
						|
scan_head([H:_P|T],N,S,PAX0,PAX1):-  
 | 
						|
  H=..[F,_Y|Args],
 | 
						|
  H1=..[F|Args],
 | 
						|
  (rb_lookup(H1,Par,PAX0)->
 | 
						|
    rb_update(PAX0,H1,[ch(N,S)|Par],PAX2)
 | 
						|
  ;
 | 
						|
    rb_insert(PAX0,H1,[ch(N,S)],PAX2)
 | 
						|
  ),
 | 
						|
  scan_head(T,N,S,PAX2,PAX1).
 | 
						|
 | 
						|
/* generates the grounding of a model 
 | 
						|
*/
 | 
						|
generate_ground(L1,GA):-
 | 
						|
  find_modes(Modes),
 | 
						|
  find_ground_atoms_modes(Modes,[],GA),
 | 
						|
  findall(rule(N,V,HL,BL),rule_by_num(N,V,_NH,HL,BL),LR),
 | 
						|
  ground_rules(LR,[],L1).
 | 
						|
/*
 | 
						|
generate_ground(L1,GA):-
 | 
						|
  find_modes(Modes),
 | 
						|
%  get_types(Modes,[],Types),
 | 
						|
  rb_new(Types0),
 | 
						|
  get_constants_types(Modes,Types0,Types1),
 | 
						|
  rb_visit(Types1,TypesL),
 | 
						|
  asser_all_const(TypesL),
 | 
						|
  find_ground_atoms_modes(Modes,[],GA),
 | 
						|
  format("Atoms ~p~n",[GA]),
 | 
						|
  findall(rule(N,V,HL,BL),rule_by_num(N,V,_NH,HL,BL),LR),
 | 
						|
  ground_rules(LR,[],L1).
 | 
						|
*/
 | 
						|
 | 
						|
generate_ground1(N,N,_O,L0,L):-!,
 | 
						|
  remove_duplicates(L0,L).
 | 
						|
 | 
						|
generate_ground1(N0,N,O,L0,L1):-
 | 
						|
  %format("Ex ~d~n",[N0]),
 | 
						|
  %(N0=320->bp;true),
 | 
						|
  generate_goal1(O,N0,[],GL),
 | 
						|
  generate_ground1_goals(GL,[],Exp0),
 | 
						|
  append(Exp0,Exp1),
 | 
						|
  %length(Exp1,Len),write(Len),nl,
 | 
						|
  remove_head(Exp1,Exp),
 | 
						|
  append(Exp,L0,L2),
 | 
						|
%  add_to_tree(Exp,L0,L2),
 | 
						|
  %write(add_to_tree),
 | 
						|
%  flush_output,
 | 
						|
  N1 is N0+1,
 | 
						|
  generate_ground1(N1,N,O,L2,L1).
 | 
						|
 | 
						|
generate_ground1_goals([],Exp,Exp).
 | 
						|
 | 
						|
generate_ground1_goals([H|T],Exp0,Exp):-
 | 
						|
  setting(depth_bound,DB),
 | 
						|
  findall(Deriv,inference_ib:find_deriv_inf1([H],DB,Deriv),Exp1),
 | 
						|
  append(Exp0,Exp1,Exp2),
 | 
						|
  generate_ground1_goals(T,Exp2,Exp).
 | 
						|
 | 
						|
add_to_tree([],L,L).
 | 
						|
 | 
						|
add_to_tree([(R,S)|T],L0,L):-
 | 
						|
  %write(t),
 | 
						|
  (rb_lookup((R,S),_,L0)->
 | 
						|
    L1=L0
 | 
						|
  ;
 | 
						|
    rb_insert(L0,(R,S),true,L1)
 | 
						|
  ),
 | 
						|
  add_to_tree(T,L1,L).
 | 
						|
 | 
						|
generate_ground2(N,N,_O,L,L):-%write(fine),nl,
 | 
						|
  !.
 | 
						|
 | 
						|
generate_ground2(N0,N,O,L0,L1):-
 | 
						|
  generate_goal(O,N0,[],GL),
 | 
						|
  %format("Ex ~d~n",[N0]),
 | 
						|
  setting(depth_bound,DB),
 | 
						|
  findall(Deriv,inference_ib:find_deriv_inf1(GL,DB,Deriv),Exp0),
 | 
						|
  append(Exp0,Exp1),
 | 
						|
  remove_head(Exp1,Exp),
 | 
						|
  add_to_list(Exp,L0,L2),
 | 
						|
  N1 is N0+1,
 | 
						|
  generate_ground2(N1,N,O,L2,L1).
 | 
						|
 | 
						|
add_to_list([],L,L).
 | 
						|
 | 
						|
add_to_list([(R,S)|T],L0,L):-
 | 
						|
  (member(((R,S)-_),L0)->
 | 
						|
    L1=L0
 | 
						|
  ;
 | 
						|
    L1=[((R,S)-true)|L0]
 | 
						|
  ),
 | 
						|
  add_to_list(T,L1,L).
 | 
						|
 | 
						|
 | 
						|
 | 
						|
get_constants_types([],Types,Types).
 | 
						|
 | 
						|
get_constants_types([H|T],Types0,Types1):-
 | 
						|
  H=..[F|Args],
 | 
						|
  length(Args,N),
 | 
						|
  length(Args1,N),  
 | 
						|
  H1=..[F,Mod|Args1],
 | 
						|
  get_const_atom(Args,Args1,Mod,Args1,H1,Types0,Types2),
 | 
						|
  get_constants_types(T,Types2,Types1).
 | 
						|
 | 
						|
get_const_atom([],[],_Mod,_Args1,_H,Types,Types).
 | 
						|
  
 | 
						|
get_const_atom([+Type|TT],[V|TV],Mod,Args1,H,Types0,Types1):-
 | 
						|
  delete(Args1,V,Vars),
 | 
						|
  setof(V,(Vars,Mod)^H,L),
 | 
						|
  insert_const(L,Type,Types0,Types2),
 | 
						|
  get_const_atom(TT,TV,Mod,Args1,H,Types2,Types1).
 | 
						|
  
 | 
						|
get_const_atom([-Type|TT],[V|TV],Mod,Args1,H,Types0,Types1):-
 | 
						|
  delete(Args1,V,Vars),
 | 
						|
  setof(V,(Vars,Mod)^H,L),
 | 
						|
  insert_const(L,Type,Types0,Types2),
 | 
						|
  get_const_atom(TT,TV,Mod,Args1,H,Types2,Types1).
 | 
						|
 | 
						|
insert_const(L,Type,Types0,Types1):-
 | 
						|
  (rb_lookup(Type,LA,Types0)->
 | 
						|
    append(L,LA,LP),
 | 
						|
    remove_duplicates(LP,LPP),
 | 
						|
    rb_update(Types0,Type,LPP,Types1)
 | 
						|
  ;
 | 
						|
    rb_insert(Types0,Type,L,Types1)
 | 
						|
  ).
 | 
						|
 | 
						|
asser_all_const([]).
 | 
						|
 | 
						|
asser_all_const([Type-Const|T]):-
 | 
						|
  format("Type ~a const ~p~n",[Type,Const]),
 | 
						|
  assert_const(Const,Type),
 | 
						|
  asser_all_const(T).
 | 
						|
    
 | 
						|
assert_const([],_Type).
 | 
						|
  
 | 
						|
assert_const([H|T],Type):-
 | 
						|
  At=..[Type,H],
 | 
						|
  assertz(At),
 | 
						|
  assert_const(T,Type).
 | 
						|
  
 | 
						|
  
 | 
						|
/* generates the grounding of a set of rules 
 | 
						|
*/
 | 
						|
ground_rules([],L,L):-!.
 | 
						|
 | 
						|
ground_rules([rule(N,V,HL,BL)|T],L0,L1):-
 | 
						|
  HL=[A:_P|_T],
 | 
						|
  A=..[_F,Y|_Args],
 | 
						|
  remove_module_head(HL,HL1),
 | 
						|
  remove_module(BL,BL1),
 | 
						|
  setof((N,V,HL1,BL1),Y^(ground_head(HL),ground_body(BL)),L),!,
 | 
						|
  append(L0,L,L2),
 | 
						|
  ground_rules(T,L2,L1).
 | 
						|
 | 
						|
ground_rules([_H|T],L0,L1):-
 | 
						|
  ground_rules(T,L0,L1).
 | 
						|
 | 
						|
/* removes the module (example) argument from the atoms of a head
 | 
						|
*/
 | 
						|
remove_module_head(['':P],['':P]):-!.
 | 
						|
 | 
						|
remove_module_head([H:P|T],[H1:P|T1]):-
 | 
						|
  H=..[F,_Y|Args],
 | 
						|
  H1=..[F|Args],
 | 
						|
  remove_module_head(T,T1).
 | 
						|
 | 
						|
/* removes the module (example) argument from the atoms of a body
 | 
						|
*/
 | 
						|
remove_module([],[]):-!.
 | 
						|
 | 
						|
remove_module([\+H|T],[\+H1|T1]):-!,
 | 
						|
  H=..[P,_Y|Args],
 | 
						|
  H1=..[P|Args],
 | 
						|
  remove_module(T,T1).
 | 
						|
 | 
						|
remove_module([H|T],[H1|T1]):-
 | 
						|
  H=..[P,_Y|Args],
 | 
						|
  H1=..[P|Args],
 | 
						|
  remove_module(T,T1).
 | 
						|
 | 
						|
/* adds the module (example) argument from the atoms of a body
 | 
						|
the value of the argument is Y
 | 
						|
*/
 | 
						|
add_module([],_Y,[]):-!.
 | 
						|
 | 
						|
add_module([\+H|T],Y,[\+H1|T1]):-!,
 | 
						|
  H=..[P|Args],
 | 
						|
  H1=..[P,Y|Args],
 | 
						|
  add_module(T,Y,T1).
 | 
						|
 | 
						|
add_module([H|T],Y,[H1|T1]):-
 | 
						|
  H=..[P|Args],
 | 
						|
  H1=..[P,Y|Args],
 | 
						|
  add_module(T,Y,T1).
 | 
						|
 | 
						|
/* instantiates a head
 | 
						|
*/
 | 
						|
/* instantiates a head
 | 
						|
*/
 | 
						|
ground_head(['':_P]):-!.
 | 
						|
 | 
						|
ground_head([H:_P|T]):-
 | 
						|
  \+ \+ H,!,
 | 
						|
  call(H),
 | 
						|
  ground_head(T).
 | 
						|
 | 
						|
ground_head([H:_P|T]):-
 | 
						|
  call(neg(H)),
 | 
						|
  ground_head(T).
 | 
						|
  
 | 
						|
 | 
						|
/* instantiates a body
 | 
						|
*/
 | 
						|
ground_body([]):-!.
 | 
						|
 | 
						|
ground_body([\+H|T]):-!,
 | 
						|
  \+call(H),
 | 
						|
  ground_body(T).
 | 
						|
 | 
						|
ground_body([H|T]):-
 | 
						|
  call(H),
 | 
						|
  ground_body(T).
 | 
						|
/*
 | 
						|
ground_head(['':_P]):-!.
 | 
						|
 | 
						|
ground_head([H:_P|T]):-
 | 
						|
  H=..[F|Args],
 | 
						|
  length(Args,N),
 | 
						|
  length(Args1,N),
 | 
						|
  H1=..[F|Args1],
 | 
						|
  modeh(_,H1),
 | 
						|
  instantiate_args(Args1,Args),
 | 
						|
  ground_head(T).
 | 
						|
 | 
						|
instantiate_args([],[]).
 | 
						|
 | 
						|
instantiate_args([+Type|T],[V|T1]):-!,
 | 
						|
  A=..[Type,V],
 | 
						|
  call(A),
 | 
						|
  instantiate_args(T,T1).
 | 
						|
  
 | 
						|
instantiate_args([-Type|T],[V|T1]):-
 | 
						|
  A=..[Type,V],
 | 
						|
  call(A),
 | 
						|
  instantiate_args(T,T1).
 | 
						|
*/
 | 
						|
 | 
						|
/* instantiates a body
 | 
						|
*/
 | 
						|
/*
 | 
						|
ground_body([]):-!.
 | 
						|
 | 
						|
ground_body([\+H|T]):-!,
 | 
						|
  H=..[F|Args],
 | 
						|
  length(Args,N),
 | 
						|
  length(Args1,N),
 | 
						|
  H1=..[F|Args1],
 | 
						|
  modeb(_,H1),
 | 
						|
  instantiate_args(Args1,Args),
 | 
						|
  ground_body(T).
 | 
						|
 | 
						|
ground_body([H|T]):-
 | 
						|
  H=..[F|Args],
 | 
						|
  length(Args,N),
 | 
						|
  length(Args1,N),
 | 
						|
  H1=..[F|Args1],
 | 
						|
  modeb(_,H1),
 | 
						|
  instantiate_args(Args1,Args),
 | 
						|
  ground_body(T).
 | 
						|
*/
 | 
						|
/* returns the set of modes specified in the language bias
 | 
						|
*/
 | 
						|
find_modes(Modes):-
 | 
						|
  findall(Pred,modeh(_,Pred),L0),
 | 
						|
  findall(Pred,modeb(_,Pred),L1),
 | 
						|
  findall(Pred,mode(_,Pred),L2),
 | 
						|
  append(L0,L1,L3),
 | 
						|
  append(L3,L2,Modes).
 | 
						|
 | 
						|
get_types([],L,L).
 | 
						|
 | 
						|
get_types([H|T],L0,L1):-
 | 
						|
  H=..[_F|Args],
 | 
						|
  remove_io(Args,L0,L2),
 | 
						|
  get_types(T,L2,L1).
 | 
						|
 | 
						|
remove_io([],L,L).
 | 
						|
 | 
						|
remove_io([+H|T],L0,L1):-
 | 
						|
  (member(H,L0)->
 | 
						|
    L2=L0
 | 
						|
  ;
 | 
						|
    append(L0,[H],L2)
 | 
						|
  ),
 | 
						|
  remove_io(T,L2,L1).
 | 
						|
 | 
						|
remove_io([-H|T],L0,L1):-
 | 
						|
  (member(H,L0)->
 | 
						|
    L2=L0
 | 
						|
  ;
 | 
						|
    append(L0,[H],L2)
 | 
						|
  ),
 | 
						|
  remove_io(T,L2,L1).
 | 
						|
 | 
						|
/* find all the ground atoms for each mode 
 | 
						|
*/
 | 
						|
find_ground_atoms_modes([],GA,GA):-!.
 | 
						|
    
 | 
						|
find_ground_atoms_modes([A|T],GA0,GA1):-
 | 
						|
  A=..[P|Args],
 | 
						|
  length(Args,L),
 | 
						|
  length(Args1,L),
 | 
						|
  A1=..[P,Y|Args1],
 | 
						|
  A2=..[P|Args1],
 | 
						|
  (setof(A2,Y^A1,LInst)->
 | 
						|
  /*  (setof(A2,Y^neg(A1),LInstN)->
 | 
						|
      append(LInst,LInstN,LI)
 | 
						|
    ;
 | 
						|
      LI=LInst
 | 
						|
    )*/
 | 
						|
    LI=LInst
 | 
						|
  ;
 | 
						|
    LI=[]
 | 
						|
  ),
 | 
						|
  remove_duplicates(LI,LI1),
 | 
						|
  append(GA0,LI1,GA2),
 | 
						|
  assert_all(LI1),
 | 
						|
  find_ground_atoms_modes(T,GA2,GA1).
 | 
						|
 | 
						|
/*
 | 
						|
find_ground_atoms_modes([],GA,GA):-!.
 | 
						|
    
 | 
						|
find_ground_atoms_modes([A|T],GA0,GA1):-
 | 
						|
  A=..[P|Args],
 | 
						|
  length(Args,L),
 | 
						|
  length(Args1,L),
 | 
						|
  A2=..[P|Args1],
 | 
						|
  findall(A2,instantiate_args(Args,Args1),LInst),
 | 
						|
  append(GA0,LInst,GA2),
 | 
						|
%  assert_all(LInst),
 | 
						|
  find_ground_atoms_modes(T,GA2,GA1).
 | 
						|
*/
 | 
						|
/* assert_all(L) asserts all the atoms of list L
 | 
						|
*/
 | 
						|
assert_all([]):-!.
 | 
						|
 | 
						|
assert_all([H|T]):-
 | 
						|
  assert(H),
 | 
						|
  assert_all(T).
 | 
						|
  
 | 
						|
/* choice_vars_IB(CL,CH,0,LogSize,R0,R1) given the grounding CL of an LPAD 
 | 
						|
returns the list of choice variables, the log size and an rb tree of rules R1,
 | 
						|
where each rule id is associated to the set of the substitution that instantiate
 | 
						|
it
 | 
						|
*/
 | 
						|
choice_vars_IB([],[],LogSize,LogSize,R,R):-!.
 | 
						|
 | 
						|
choice_vars_IB([d(N,S,_H,_B)|T],CH,LogSize0,LogSize1,R0,R1):-
 | 
						|
  (rb_lookup(N,L,R0)->
 | 
						|
    (member(S,L)->
 | 
						|
      CH=CH1,
 | 
						|
      R2=R0      
 | 
						|
    ;
 | 
						|
      rb_update(R0,N,[S|L],R2),
 | 
						|
      CH=[ch(N,S)|CH1]
 | 
						|
    )
 | 
						|
  ;
 | 
						|
    rb_insert(R0,N,[S],R2),
 | 
						|
    CH=[ch(N,S)|CH1]
 | 
						|
  ),
 | 
						|
  choice_vars_IB(T,CH1,LogSize0,LogSize1,R2,R1).
 | 
						|
 | 
						|
 | 
						|
choice_vars_IB([(N,S,H,_B)|T],CH,LogSize0,LogSize1,R0,R1):-
 | 
						|
  (rb_lookup(N,L,R0)->
 | 
						|
    (member(S,L)->
 | 
						|
      LogSize2 = LogSize0,
 | 
						|
      CH=CH1,
 | 
						|
      R2=R0      
 | 
						|
    ;
 | 
						|
      rb_update(R0,N,[S|L],R2),
 | 
						|
      length(H,SizeCH),
 | 
						|
      LogSize2 is LogSize0+log(SizeCH),
 | 
						|
      CH=[ch(N,S)|CH1]
 | 
						|
    )
 | 
						|
  ;
 | 
						|
    rb_insert(R0,N,[S],R2),
 | 
						|
    length(H,SizeCH),
 | 
						|
    LogSize2 is LogSize0+log(SizeCH),
 | 
						|
    CH=[ch(N,S)|CH1]
 | 
						|
  ),
 | 
						|
  choice_vars_IB(T,CH1,LogSize2,LogSize1,R2,R1).
 | 
						|
 | 
						|
 | 
						|
generate_goal_DB(N,N,_O,GL,GL):-!.
 | 
						|
 | 
						|
generate_goal_DB(N0,N,O,G0,G1):-
 | 
						|
  generate_goal(O,N0,G0,G2),
 | 
						|
  N1 is N0+1,
 | 
						|
  generate_goal_DB(N1,N,O,G2,G1).
 | 
						|
 | 
						|
/* unused
 | 
						|
random_restarts(1,Model,SS,CLL,Model,SS,CLL,_DB):-!.
 | 
						|
 | 
						|
random_restarts(N,Model0,SS0,CLL0,Model1,SS1,CLL1,DB):-
 | 
						|
  setting(verbosity,Ver),
 | 
						|
  (Ver>4->
 | 
						|
    setting(random_restarts_number,NMax),
 | 
						|
    Num is NMax-N+1,
 | 
						|
    format("Restart number ~d~n",[Num])
 | 
						|
  ;
 | 
						|
    true
 | 
						|
  ),
 | 
						|
  randomize(Model0,ModelR),
 | 
						|
  em_iteration(ModelR,ModelR1,SSR,CLLR,DB),
 | 
						|
  (Ver>4->
 | 
						|
    format("CLL ~f~n",[CLLR])
 | 
						|
  ;
 | 
						|
    true
 | 
						|
  ),
 | 
						|
  N1 is N-1,
 | 
						|
  (CLLR>CLL0->
 | 
						|
    random_restarts(N1,ModelR1,SSR,CLLR,Model1,SS1,CLL1,DB)
 | 
						|
  ;
 | 
						|
    random_restarts(N1,Model0,SS0,CLL0,Model1,SS1,CLL1,DB)
 | 
						|
  ).
 | 
						|
*/
 | 
						|
randomize([],[]):-!.
 | 
						|
 | 
						|
randomize([rule(N,V,NH,HL,BL,LogF)|T],[rule(N,V,NH,HL1,BL,LogF)|T1]):-!,
 | 
						|
  length(HL,L),
 | 
						|
  Int is 1.0/L,
 | 
						|
  randomize_head(Int,HL,0,HL1),
 | 
						|
  randomize(T,T1).
 | 
						|
 | 
						|
randomize([H|T],[H|T1]):-
 | 
						|
  randomize(T,T1).
 | 
						|
 | 
						|
 | 
						|
randomize_head(_Int,['':_],P,['':PNull1]):-!,
 | 
						|
  PNull is 1.0-P,
 | 
						|
  (PNull>=0.0->
 | 
						|
    PNull1 =PNull
 | 
						|
  ;
 | 
						|
    PNull1=0.0
 | 
						|
  ).
 | 
						|
 | 
						|
randomize_head(_Int,[H:_],P,[H:PN]):-!,
 | 
						|
  PN is 1.0-P.
 | 
						|
 | 
						|
randomize_head(Int,[H:_|T],P,[H:PH1|NT]):-
 | 
						|
  PMax is 1.0-P,
 | 
						|
  random(0,PMax,PH1),
 | 
						|
  P1 is P+PH1,  
 | 
						|
  randomize_head(Int,T,P1,NT).
 | 
						|
 | 
						|
 | 
						|
/* asserts the model in the database
 | 
						|
*/
 | 
						|
assert_model([]):-!.
 | 
						|
 | 
						|
assert_model([def_rule(N,S,H,BL)|T]):-
 | 
						|
  assertz(def_rule(H,BL,N,S)),
 | 
						|
  assertz(def_rule_by_num(N,S,H,BL)),
 | 
						|
  assert_model(T).
 | 
						|
 | 
						|
assert_model([rule(N,V,NH,HL,BL,_LogF)|T]):-
 | 
						|
  assert_rules(HL,0,HL,BL,NH,N,V),
 | 
						|
  assertz(rule_by_num(N,V,NH,HL,BL)),
 | 
						|
  assert_model(T).
 | 
						|
 | 
						|
/* retracts the model from the database
 | 
						|
*/
 | 
						|
retract_model:-!,
 | 
						|
  retractall(rule_by_num(_,_,_,_,_)),
 | 
						|
  retractall(rule(_,_,_,_,_,_,_,_)).
 | 
						|
 | 
						|
/* returns the list of predicates specification for output atoms
 | 
						|
*/
 | 
						|
get_ouptut_atoms(O):-
 | 
						|
  findall((A/Ar),output((A/Ar)),O).
 | 
						|
 | 
						|
/* generates the list of goals that must be asked for computing the CLL
 | 
						|
and the grounding of an LPAD
 | 
						|
*/
 | 
						|
generate_goal([],_H,G,G):-!.
 | 
						|
 | 
						|
generate_goal([P/A|T],H,G0,G1):-
 | 
						|
  functor(Pred,P,A),
 | 
						|
  Pred=..[P|Rest],
 | 
						|
  Pred1=..[P,H|Rest],
 | 
						|
  findall(Pred1,call(Pred1),L),
 | 
						|
  findall(\+ Pred1,call(neg(Pred1)),LN),
 | 
						|
  append(G0,L,G2),
 | 
						|
  append(G2,LN,G3),
 | 
						|
  generate_goal(T,H,G3,G1).
 | 
						|
  
 | 
						|
generate_goal1([],_H,G,G):-!.
 | 
						|
 | 
						|
generate_goal1([P/A|T],H,G0,G1):-
 | 
						|
  functor(Pred,P,A),
 | 
						|
  Pred=..[P|Rest],
 | 
						|
  Pred1=..[P,H|Rest],
 | 
						|
  findall(Pred1,call(Pred1),L),
 | 
						|
  findall(Pred1,call(neg(Pred1)),LN),
 | 
						|
  append(G0,L,G2),
 | 
						|
  append(G2,LN,G3),
 | 
						|
  generate_goal1(T,H,G3,G1).
 | 
						|
  
 | 
						|
  
 | 
						|
 | 
						|
sum(_NS,[],[],[]):-!.  
 | 
						|
 | 
						|
sum(NS,[H0|T0],[H1|T1],[H2|T2]):-
 | 
						|
  H2 is H0+H1*NS,
 | 
						|
  sum(NS,T0,T1,T2).  
 | 
						|
  
 | 
						|
times(_NS,[],[]):-!.  
 | 
						|
 | 
						|
times(NS,[H0|T0],[H1|T1]):-
 | 
						|
  H1 is H0*NS,
 | 
						|
  times(NS,T0,T1).  
 | 
						|
 | 
						|
divide(_NS,[],[]):-!.  
 | 
						|
 | 
						|
divide(NS,[H0|T0],[H1|T1]):-
 | 
						|
  H1 is H0/NS,
 | 
						|
  divide(NS,T0,T1).  
 | 
						|
 | 
						|
/* End of computation of log likelihood and sufficient stats */
 | 
						|
 | 
						|
/* Utility predicates */
 | 
						|
set(Parameter,Value):-
 | 
						|
  retract(setting(Parameter,_)),
 | 
						|
  assert(setting(Parameter,Value)).
 | 
						|
 | 
						|
generate_file_names(File,FileKB,FileOut,FileL,FileLPAD,FileBG):-
 | 
						|
  generate_file_name(File,".kb",FileKB),
 | 
						|
  generate_file_name(File,".rules",FileOut),
 | 
						|
  generate_file_name(File,".cpl",FileLPAD),
 | 
						|
  generate_file_name(File,".l",FileL),
 | 
						|
  generate_file_name(File,".bg",FileBG).        
 | 
						|
 | 
						|
generate_file_name(File,Ext,FileExt):-
 | 
						|
  name(File,FileString),
 | 
						|
  append(FileString,Ext,FileStringExt),
 | 
						|
  name(FileExt,FileStringExt).
 | 
						|
    
 | 
						|
load_initial_model(File,Model):-
 | 
						|
  open(File,read,S),
 | 
						|
  read_clauses1(S,C),
 | 
						|
  close(S),
 | 
						|
  process_clauses(C,0,_N,[],Model).
 | 
						|
 | 
						|
process_clauses([(end_of_file,[])],N,N,Model,Model).
 | 
						|
 | 
						|
process_clauses([((H:-B),V)|T],N,N2,Model0,[rule(N,V,NH,HL,BL,0)|Model1]):-
 | 
						|
  H=(_;_),!,
 | 
						|
  list2or(HL1,H),
 | 
						|
  process_head(HL1,HL,VI),
 | 
						|
  list2and(BL0,B),
 | 
						|
  add_int_atom(BL0,BL,VI),
 | 
						|
  length(HL,LH),
 | 
						|
  listN(0,LH,NH),
 | 
						|
  N1 is N+1,
 | 
						|
%  assertz(rule(N,V,NH,HL,BL)),
 | 
						|
  process_clauses(T,N1,N2,Model0,Model1).
 | 
						|
 | 
						|
process_clauses([((H:-B),V)|T],N,N2,Model0,[rule(N,V,NH,HL,BL,0)|Model1]):-
 | 
						|
  H=(_:_),!,
 | 
						|
  list2or(HL1,H),
 | 
						|
  process_head(HL1,HL,VI),
 | 
						|
  list2and(BL0,B),
 | 
						|
  add_int_atom(BL0,BL,VI),
 | 
						|
  length(HL,LH),
 | 
						|
  listN(0,LH,NH),
 | 
						|
  N1 is N+1,
 | 
						|
%  assertz(rule(N,V1,NH,HL,BL)),
 | 
						|
  process_clauses(T,N1,N2,Model0,Model1).
 | 
						|
  
 | 
						|
process_clauses([((H:-B),V)|T],N,N2,Model0,[def_rule(N,V,H1,BL)|Model1]):-!,
 | 
						|
  list2and(BL0,B),
 | 
						|
  N1 is N+1,
 | 
						|
  add_int_atom([H|BL0],[H1|BL],_VI),
 | 
						|
%  assertz(rule(N,V1,NH,HL,BL)),
 | 
						|
  process_clauses(T,N1,N2,Model0,Model1).
 | 
						|
 | 
						|
process_clauses([(H,V)|T],N,N2,Model0,[rule(N,V,NH,HL,[],0)|Model1]):-
 | 
						|
  H=(_;_),!,
 | 
						|
  list2or(HL1,H),
 | 
						|
  process_head(HL1,HL,_VI),
 | 
						|
  length(HL,LH),
 | 
						|
  listN(0,LH,NH),
 | 
						|
  N1 is N+1,
 | 
						|
%  assertz(rule(N,V,NH,HL,[])),
 | 
						|
  process_clauses(T,N1,N2,Model0,Model1).
 | 
						|
 | 
						|
process_clauses([(H,V)|T],N,N2,Model0,[rule(N,V,NH,HL,[],0)|Model1]):-
 | 
						|
  H=(_:_),!,
 | 
						|
  list2or(HL1,H),
 | 
						|
  process_head(HL1,HL,_VI),
 | 
						|
  length(HL,LH),
 | 
						|
  listN(0,LH,NH),
 | 
						|
  N1 is N+1,
 | 
						|
%  assertz(rule(N,V,NH,HL,[])),
 | 
						|
  process_clauses(T,N1,N2,Model0,Model1).
 | 
						|
  
 | 
						|
process_clauses([(H,V)|T],N,N2,Model0,[def_rule(N,V,H1,[])|Model1]):-
 | 
						|
  add_int_atom([H],[H1],_VI),
 | 
						|
  N1 is N+1,
 | 
						|
%  assertz(rule(N,V,NH,HL,[])),
 | 
						|
  process_clauses(T,N1,N2,Model0,Model1).
 | 
						|
 | 
						|
/* if the annotation in the head are not ground, the null atom is not added
 | 
						|
and the eventual formulas are not evaluated */
 | 
						|
  
 | 
						|
process_head([H:P|T],NHL,VI):-!,
 | 
						|
    process_head_prob([H:P|T],0.0,NHL,VI).
 | 
						|
 | 
						|
process_head(HL,NHL,VI):-
 | 
						|
    process_head_random(HL,0.0,NHL,VI).
 | 
						|
 | 
						|
process_head_random([],P,['':PNull1],_VI):-
 | 
						|
  PNull is 1.0-P,
 | 
						|
  (PNull>=0.0->
 | 
						|
    PNull1 =PNull
 | 
						|
  ;
 | 
						|
    PNull1=0.0
 | 
						|
  ).
 | 
						|
  
 | 
						|
process_head_random([H|T],P,[H1:PH1|NT],VI):-
 | 
						|
  add_int_atom([H],[H1],VI),
 | 
						|
  PMax is 1.0-P,
 | 
						|
  random(0,PMax,PH1),
 | 
						|
  P1 is P+PH1,  
 | 
						|
  process_head_random(T,P1,NT,VI).
 | 
						|
 | 
						|
    
 | 
						|
process_head_prob([H:PH],P,[H1:PH1],VI):-
 | 
						|
  add_int_atom([H],[H1],VI),
 | 
						|
  PH1 is PH,
 | 
						|
  PNull is 1.0-P-PH1,
 | 
						|
  PNull<1e-10,!.
 | 
						|
 | 
						|
process_head_prob([H:PH],P,[H1:PH1,'':PNull],VI):-
 | 
						|
  add_int_atom([H],[H1],VI),
 | 
						|
  PH1 is PH,
 | 
						|
  PNull is 1.0-P-PH1.
 | 
						|
  
 | 
						|
process_head_prob([H:PH|T],P,[H1:PH1|NT],VI):-
 | 
						|
  add_int_atom([H],[H1],VI),
 | 
						|
  PH1 is PH,
 | 
						|
  P1 is P+PH1,
 | 
						|
  process_head_prob(T,P1,NT,VI).
 | 
						|
 | 
						|
 | 
						|
add_int_atom([],[],_VI).
 | 
						|
 | 
						|
add_int_atom([H|T],[H|T1],VI):-
 | 
						|
  inference_ib:builtin(H),!,
 | 
						|
  add_int_atom(T,T1,VI).
 | 
						|
 | 
						|
add_int_atom([\+ H|T],[\+ H1|T1],VI):-!,
 | 
						|
  H=..[F|Args],
 | 
						|
  H1=..[F,VI|Args],
 | 
						|
  add_int_atom(T,T1,VI).
 | 
						|
 | 
						|
add_int_atom([H|T],[H1|T1],VI):-
 | 
						|
  H=..[F|Args],
 | 
						|
  H1=..[F,VI|Args],
 | 
						|
  add_int_atom(T,T1,VI).
 | 
						|
 | 
						|
/* predicates for reading in the program clauses */
 | 
						|
read_clauses1(S,Clauses):-
 | 
						|
    read_clauses_ground_body1(S,Clauses).
 | 
						|
 | 
						|
 | 
						|
read_clauses_ground_body1(S,[(Cl,V)|Out]):-
 | 
						|
  read_term(S,Cl,[variable_names(V)]),
 | 
						|
  (Cl=end_of_file->
 | 
						|
    Out=[]
 | 
						|
  ;
 | 
						|
    read_clauses_ground_body1(S,Out)
 | 
						|
  ).
 | 
						|
 | 
						|
 | 
						|
assert_rules([],_Pos,_HL,_BL,_Nh,_N,_V1):-!.
 | 
						|
 | 
						|
assert_rules(['':_P],_Pos,_HL,_BL,_Nh,_N,_V1):-!.
 | 
						|
 | 
						|
assert_rules([H:P|T],Pos,HL,BL,NH,N,V1):-
 | 
						|
  assertz(rule(H,P,Pos,N,V1,NH,HL,BL)),
 | 
						|
  Pos1 is Pos+1,
 | 
						|
  assert_rules(T,Pos1,HL,BL,NH,N,V1).
 | 
						|
 | 
						|
  
 | 
						|
listN(N,N,[]):-!.
 | 
						|
 | 
						|
listN(NIn,N,[NIn|T]):-
 | 
						|
  N1 is NIn+1,
 | 
						|
  listN(N1,N,T).
 | 
						|
 | 
						|
list0(N,N,[]):-!.
 | 
						|
 | 
						|
list0(NIn,N,[0|T]):-
 | 
						|
  N1 is NIn+1,
 | 
						|
  list0(N1,N,T).
 | 
						|
 | 
						|
list1(N,N,[]):-!.
 | 
						|
 | 
						|
list1(NIn,N,[1|T]):-
 | 
						|
  N1 is NIn+1,
 | 
						|
  list1(N1,N,T).
 | 
						|
 | 
						|
/* end of predicates for parsing an input file containing a program */
 | 
						|
 | 
						|
 | 
						|
load_models(File):-
 | 
						|
    open(File,read,Stream),
 | 
						|
    read_models(Stream,0,Ex),
 | 
						|
    retractall(ex(_)),
 | 
						|
    assert(ex(Ex)),
 | 
						|
    close(Stream).
 | 
						|
    
 | 
						|
read_models(Stream,N,NEx):-
 | 
						|
    read(Stream,begin(model(_Name))),!,
 | 
						|
    %format("Model ~p Y ~d~n",[Name,N]),
 | 
						|
    read_all_atoms(Stream,N),
 | 
						|
    N1 is N+1,
 | 
						|
    read_models(Stream,N1,NEx).
 | 
						|
 | 
						|
read_models(_S,N,N).
 | 
						|
 | 
						|
read_all_atoms(Stream,Name):-
 | 
						|
      read(Stream,At),
 | 
						|
      (At \=end(model(_Name))->
 | 
						|
        (At=neg(Atom)->    
 | 
						|
      Atom=..[Pred|Args],
 | 
						|
          Atom1=..[Pred,Name|Args],
 | 
						|
          assertz(neg(Atom1))
 | 
						|
        ;
 | 
						|
          At=..[Pred|Args],
 | 
						|
          Atom1=..[Pred,Name|Args],
 | 
						|
          assertz(Atom1)
 | 
						|
    ),
 | 
						|
        read_all_atoms(Stream,Name)
 | 
						|
;
 | 
						|
    true
 | 
						|
  ).    
 | 
						|
 | 
						|
 | 
						|
 | 
						|
list2or([],true):-!.
 | 
						|
 | 
						|
list2or([X],X):-
 | 
						|
    X\=;(_,_),!.
 | 
						|
 | 
						|
list2or([H|T],(H ; Ta)):-!,
 | 
						|
    list2or(T,Ta).
 | 
						|
 | 
						|
list2and([],true):-!.
 | 
						|
 | 
						|
list2and([X],X):-
 | 
						|
    X\=(_,_),!.
 | 
						|
 | 
						|
list2and([H|T],(H,Ta)):-!,
 | 
						|
    list2and(T,Ta).
 | 
						|
    
 | 
						|
lgamma1(A,B):-
 | 
						|
  (A>=1.0->
 | 
						|
    lgamma(A,B)
 | 
						|
  ;
 | 
						|
    B=0.0
 | 
						|
  ).
 | 
						|
write_model([],_Stream):-!.
 | 
						|
 | 
						|
write_model([def_rule(_N,_S,H,[])|Rest],Stream):-!,
 | 
						|
  copy_term(H,H1),
 | 
						|
    numbervars(H1,0,_M),
 | 
						|
    remove_int_atom(H1,H2),
 | 
						|
    format(Stream,"~p.~n~n",[H2]),
 | 
						|
    write_model(Rest,Stream).
 | 
						|
 | 
						|
 | 
						|
write_model([def_rule(_N,_S,H,BL)|Rest],Stream):-!,
 | 
						|
  copy_term((H,BL),(H1,BL1)),
 | 
						|
    numbervars((H1,BL1),0,_M),
 | 
						|
  remove_int_atom(H1,H2),
 | 
						|
    format(Stream,"~p :- ~n",[H2]),
 | 
						|
    write_body(Stream,BL1),
 | 
						|
    format(Stream,".~n~n",[]),
 | 
						|
    write_model(Rest,Stream).
 | 
						|
 | 
						|
write_model([rule(_N,_V,_NH,HL,BL,_LogF)|Rest],Stream):-
 | 
						|
  copy_term((HL,BL),(HL1,BL1)),
 | 
						|
    numbervars((HL1,BL1),0,_M),
 | 
						|
    write_disj_clause(Stream,(HL1:-BL1)),
 | 
						|
    format(Stream,".~n~n",[]),
 | 
						|
    write_model(Rest,Stream).
 | 
						|
 | 
						|
 | 
						|
write_disj_clause(S,(H:-[])):-!,
 | 
						|
  write_head(S,H).
 | 
						|
    
 | 
						|
write_disj_clause(S,(H:-B)):-
 | 
						|
  write_head(S,H),
 | 
						|
  write(S,' :-'),
 | 
						|
  nl(S),
 | 
						|
  write_body(S,B).
 | 
						|
  
 | 
						|
write_head(S,[A:1.0|_Rest]):-!,
 | 
						|
  remove_int_atom(A,A1),
 | 
						|
    format(S,"~p",[A1]).
 | 
						|
  
 | 
						|
write_head(S,[A:P,'':_P]):-!,
 | 
						|
  remove_int_atom(A,A1),
 | 
						|
    format(S,"~p:~f",[A1,P]).
 | 
						|
 | 
						|
write_head(S,[A:P]):-!,
 | 
						|
  remove_int_atom(A,A1),
 | 
						|
    format(S,"~p:~f",[A1,P]).
 | 
						|
 | 
						|
write_head(S,[A:P|Rest]):-
 | 
						|
  remove_int_atom(A,A1),
 | 
						|
    format(S,"~p:~f ; ",[A1,P]),
 | 
						|
    write_head(S,Rest).
 | 
						|
 | 
						|
write_body(S,[\+ A]):-
 | 
						|
  inference_ib:builtin(A),!,
 | 
						|
    format(S,"\t\\+ ~p",[A]).
 | 
						|
 | 
						|
write_body(S,[\+ A]):-!,
 | 
						|
  remove_int_atom(A,A1),
 | 
						|
    format(S,"\t\\+ ~p",[A1]).
 | 
						|
 
 | 
						|
write_body(S,[A]):-
 | 
						|
  inference_ib:builtin(A),!,
 | 
						|
    format(S,"\t~p",[A]).
 | 
						|
 | 
						|
write_body(S,[A]):-!,
 | 
						|
  remove_int_atom(A,A1),
 | 
						|
    format(S,"\t~p",[A1]).
 | 
						|
    
 | 
						|
write_body(S,[\+ A|T]):-
 | 
						|
  inference_ib:builtin(A),!,
 | 
						|
    format(S,"\t\\+ ~p,~n",[A]),
 | 
						|
    write_body(S,T).
 | 
						|
 | 
						|
write_body(S,[\+ A|T]):-!,
 | 
						|
  remove_int_atom(A,A1),
 | 
						|
    format(S,"\t\\+ ~p,~n",[A1]),
 | 
						|
    write_body(S,T).
 | 
						|
 | 
						|
write_body(S,[A|T]):-
 | 
						|
  inference_ib:builtin(A),!,
 | 
						|
    format(S,"\t~p,~n",[A]),
 | 
						|
    write_body(S,T).
 | 
						|
 | 
						|
write_body(S,[A|T]):-
 | 
						|
  remove_int_atom(A,A1),
 | 
						|
    format(S,"\t~p,~n",[A1]),
 | 
						|
    write_body(S,T).
 | 
						|
 | 
						|
    
 | 
						|
remove_int_atom(A,A1):-
 | 
						|
  A=..[F,_|T],
 | 
						|
  A1=..[F|T].
 | 
						|
 | 
						|
build_ground_lpad([],[]):-!.
 | 
						|
 | 
						|
build_ground_lpad([d(R,S)|T],[d(R,S,Head,Body)|T1]):-!,
 | 
						|
  %write(g),
 | 
						|
  user:def_rule_by_num(R,S,Head,Body),
 | 
						|
  build_ground_lpad(T,T1).
 | 
						|
 | 
						|
build_ground_lpad([(R,S)|T],[(R,S,Head,Body)|T1]):-
 | 
						|
  %write(g),
 | 
						|
  user:rule_by_num(R,S,_,Head,Body),
 | 
						|
  build_ground_lpad(T,T1).
 | 
						|
 | 
						|
/*
 | 
						|
remove_head([],[]).
 | 
						|
 | 
						|
remove_head([(_N,R,S)|T],[(R,S)|T1]):-
 | 
						|
  remove_head(T,T1).
 | 
						|
*/
 | 
						|
 | 
						|
generate_nth_pos(I, I, [Head|_], Head):-!.
 | 
						|
generate_nth_pos(I, IN, [_|List], El) :-
 | 
						|
  I1 is I+1,
 | 
						|
  generate_nth_pos(I1, IN, List, El).
 | 
						|
 | 
						|
my_get_value(K,V):-
 | 
						|
  recorded(K,V,_R).
 | 
						|
  
 | 
						|
my_set_value(K,V):-
 | 
						|
  eraseall(K),
 | 
						|
  recorda(K,V,_R).
 | 
						|
 | 
						|
delete_matching([],_El,[]).
 | 
						|
 | 
						|
delete_matching([El|T],El,T1):-!,
 | 
						|
        delete_matching(T,El,T1).
 | 
						|
 | 
						|
delete_matching([H|T],El,[H|T1]):-
 | 
						|
        delete_matching(T,El,T1).
 | 
						|
 |