1268 lines
		
	
	
		
			27 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
		
		
			
		
	
	
			1268 lines
		
	
	
		
			27 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
|   | /*
 | ||
|  | 
 | ||
|  | EMBLEM and SLIPCASE | ||
|  | 
 | ||
|  | Copyright (c) 2011, Fabrizio Riguzzi and Elena Bellodi | ||
|  | 
 | ||
|  | This package uses the library cudd, see http://vlsi.colorado.edu/~fabio/CUDD/
 | ||
|  | for the relative license. | ||
|  | 
 | ||
|  | */ | ||
|  | 
 | ||
|  | #include <math.h>
 | ||
|  | #include <stdlib.h>
 | ||
|  | #include <stdio.h>
 | ||
|  | #include <string.h>
 | ||
|  | #include "cuddInt.h"
 | ||
|  | #include "YapInterface.h"
 | ||
|  | #define LOGZERO log(0.000001)
 | ||
|  | #define CACHE_SLOTS 1 
 | ||
|  | #define UNIQUE_SLOTS 1
 | ||
|  | 
 | ||
|  | 
 | ||
|  | typedef struct | ||
|  | { | ||
|  |   int nVal,nRule; | ||
|  |   int firstBoolVar; | ||
|  | } variable; | ||
|  | 
 | ||
|  | 
 | ||
|  | typedef struct  | ||
|  | { | ||
|  |   DdNode *key; | ||
|  |   double value; | ||
|  | } rowel; | ||
|  | 
 | ||
|  | typedef struct   | ||
|  | { | ||
|  |   int cnt; | ||
|  |   rowel *row; | ||
|  | } tablerow; | ||
|  | 
 | ||
|  | tablerow * table; | ||
|  | 
 | ||
|  | static variable * vars; | ||
|  | static variable ** vars_ex; | ||
|  | static int * bVar2mVar; | ||
|  | static int ** bVar2mVar_ex; | ||
|  | static double * sigma; | ||
|  | static double ***eta; | ||
|  | static double ***eta_temp; | ||
|  | static double **arrayprob; | ||
|  | static int *rules; | ||
|  | static DdManager *mgr; | ||
|  | static DdManager **mgr_ex; | ||
|  | static int *nVars; | ||
|  | static int *nVars_ex; | ||
|  | static int nRules; | ||
|  | double * probs; | ||
|  | double * nodes_probs_ex; | ||
|  | double ** probs_ex; | ||
|  | static int * boolVars; | ||
|  | static int * boolVars_ex;  | ||
|  | tablerow * nodesB; | ||
|  | tablerow * nodesF; | ||
|  | int ex,cycle; | ||
|  | DdNode *** nodesToVisit; | ||
|  | int * NnodesToVisit; | ||
|  | double * example_prob; | ||
|  | static int ret_prob(void); | ||
|  | double Prob(DdNode *node,int comp_par); | ||
|  | static int end_bdd(void); | ||
|  | static int init_test(void); | ||
|  | static int add_var(void); | ||
|  | static int init(void); | ||
|  | static int end(void); | ||
|  | static int EM(void); | ||
|  | static int Q(void); | ||
|  | double ProbPath(DdNode *node, int comp_par); | ||
|  | static int rec_deref(void); | ||
|  | int indexMvar(DdNode *node); | ||
|  | void Forward(DdNode *node); | ||
|  | void GetForward(DdNode *node, double ForwProbPath); | ||
|  | void UpdateForward(DdNode * node); | ||
|  | double GetOutsideExpe(DdNode *root,double ex_prob); | ||
|  | void Maximization(void); | ||
|  | static double Expectation(DdNode **nodes_ex, int lenNodes); | ||
|  | void init_my_predicates(void); | ||
|  | FILE *open_file(char *filename, const char *mode); | ||
|  | tablerow* init_table(int varcnt); | ||
|  | double * get_value(tablerow *tab,  DdNode *node); | ||
|  | void add_or_replace_node(tablerow *tab, DdNode *node, double value); | ||
|  | void add_node(tablerow *tab, DdNode *node, double value); | ||
|  | void destroy_table(tablerow *tab,int varcnt); | ||
|  | 
 | ||
|  | static int init(void) | ||
|  | { | ||
|  |   int j,i; | ||
|  |   YAP_Term arg1,arg2,list; | ||
|  | 
 | ||
|  |   ex=0; | ||
|  |   cycle=0; | ||
|  |   arg1=YAP_ARG1; | ||
|  |   arg2=YAP_ARG2; | ||
|  |   nRules=YAP_IntOfTerm(arg1); | ||
|  | 
 | ||
|  |   vars_ex=NULL; | ||
|  |   nVars_ex=NULL; | ||
|  |   eta= (double ***) malloc(nRules * sizeof(double **)); | ||
|  |   eta_temp= (double ***) malloc(nRules * sizeof(double **)); | ||
|  |   rules= (int *) malloc(nRules * sizeof(int)); | ||
|  |   arrayprob=(double **) malloc(nRules * sizeof(double *)); | ||
|  |   probs_ex=NULL; | ||
|  |   bVar2mVar_ex=NULL; | ||
|  |   boolVars_ex=NULL; | ||
|  |   mgr_ex=NULL; | ||
|  |   nodes_probs_ex=NULL; | ||
|  |   list=arg2; | ||
|  |   for (j=0;j<nRules;j++)   | ||
|  |   { | ||
|  |     rules[j]=YAP_IntOfTerm(YAP_HeadOfTerm(list)); | ||
|  |     list=YAP_TailOfTerm(list); | ||
|  |     eta[j]= (double **) malloc((rules[j]-1)*sizeof(double *)); | ||
|  |     eta_temp[j]= (double **) malloc((rules[j]-1)*sizeof(double *)); | ||
|  |     arrayprob[j]= (double *) malloc((rules[j]-1)*sizeof(double)); | ||
|  |     for (i=0;i<rules[j]-1;i++) | ||
|  |     { | ||
|  |       eta[j][i]=(double *) malloc(2*sizeof(double)); | ||
|  |       eta_temp[j][i]=(double *) malloc(2*sizeof(double)); | ||
|  |     } | ||
|  |   } | ||
|  |   return 1; | ||
|  | } | ||
|  | 
 | ||
|  | static int init_bdd(void)   | ||
|  | { | ||
|  |   mgr=Cudd_Init(0,0,UNIQUE_SLOTS,CACHE_SLOTS,5120); | ||
|  |   Cudd_AutodynEnable(mgr, CUDD_REORDER_GROUP_SIFT); | ||
|  |   Cudd_SetMaxCacheHard(mgr, 0); | ||
|  |   Cudd_SetLooseUpTo(mgr, 0); | ||
|  |   Cudd_SetMinHit(mgr, 15); | ||
|  |   mgr_ex=(DdManager **) realloc(mgr_ex, (ex+1)* sizeof(DdManager *));  | ||
|  |   mgr_ex[ex]=mgr; | ||
|  |    | ||
|  |   bVar2mVar_ex=(int **) realloc(bVar2mVar_ex, (ex+1)* sizeof(int *)); | ||
|  |   bVar2mVar_ex[ex]=NULL; | ||
|  |   bVar2mVar=bVar2mVar_ex[ex]; | ||
|  | 
 | ||
|  |   vars_ex=(variable **) realloc(vars_ex, (ex+1)* sizeof(variable *)); | ||
|  |   vars_ex[ex]=NULL; | ||
|  |   vars=vars_ex[ex]; | ||
|  |    | ||
|  |   nVars_ex=(int *) realloc(nVars_ex, (ex+1)* sizeof(int )); | ||
|  |   nVars=nVars_ex+ex; | ||
|  |   *nVars=0; | ||
|  | 
 | ||
|  |   probs_ex=(double **) realloc(probs_ex, (ex+1)* sizeof(double *));  | ||
|  |   probs_ex[ex]=NULL; | ||
|  |   probs=probs_ex[ex]; | ||
|  |    | ||
|  |   boolVars_ex=(int *) realloc(boolVars_ex, (ex+1)* sizeof(int )); | ||
|  |   boolVars=boolVars_ex+ex; | ||
|  |   *boolVars=0; | ||
|  | 
 | ||
|  |   return 1; | ||
|  | } | ||
|  | 
 | ||
|  | static int end_bdd(void) | ||
|  | { | ||
|  | 
 | ||
|  |   bVar2mVar_ex[ex]=bVar2mVar; | ||
|  |   probs_ex[ex]=probs; | ||
|  |   vars_ex[ex]=vars; | ||
|  |   ex=ex+1; | ||
|  |   return 1; | ||
|  | } | ||
|  | 
 | ||
|  | 
 | ||
|  | 
 | ||
|  | static int init_test(void) | ||
|  | { | ||
|  |   YAP_Term arg1;   | ||
|  | 
 | ||
|  |   arg1=YAP_ARG1; | ||
|  |   nRules=YAP_IntOfTerm(arg1); | ||
|  | 
 | ||
|  | 
 | ||
|  |   mgr=Cudd_Init(0,0,UNIQUE_SLOTS,CACHE_SLOTS,0); | ||
|  |   Cudd_AutodynEnable(mgr, CUDD_REORDER_GROUP_SIFT); | ||
|  |   Cudd_SetMaxCacheHard(mgr, 1024*1024*1024); | ||
|  |   Cudd_SetLooseUpTo(mgr, 1024*1024*512); | ||
|  |   rules= (int *) malloc(nRules * sizeof(int));   | ||
|  |    | ||
|  |   bVar2mVar=NULL; | ||
|  |   probs=NULL;   | ||
|  |   vars=NULL; | ||
|  |    | ||
|  |   nVars=(int *) malloc(sizeof(int )); | ||
|  |   *nVars=0; | ||
|  |    | ||
|  |   boolVars=(int *) malloc(sizeof(int )); | ||
|  |   *boolVars=0; | ||
|  |    | ||
|  |   return 1; | ||
|  | } | ||
|  | 
 | ||
|  | static int end_test(void) | ||
|  | { | ||
|  |   free(bVar2mVar); | ||
|  |   free(vars); | ||
|  |   free(nVars); | ||
|  |   free(boolVars); | ||
|  |   Cudd_Quit(mgr); | ||
|  |   free(probs); | ||
|  |   free(rules); | ||
|  |   return 1; | ||
|  | } | ||
|  | 
 | ||
|  | 
 | ||
|  | 
 | ||
|  | static double Expectation(DdNode **nodes_ex,int lenNodes) | ||
|  | { | ||
|  |   int i; | ||
|  |   double rootProb,CLL=0; | ||
|  |    | ||
|  |   for(i=0;i<lenNodes;i++)   | ||
|  |   { | ||
|  |     if (!Cudd_IsConstant(nodes_ex[i])) | ||
|  |     { | ||
|  |       mgr=mgr_ex[i]; | ||
|  |       probs=probs_ex[i]; | ||
|  |       boolVars=boolVars_ex+i; | ||
|  |       nodesB=init_table(*boolVars); | ||
|  |       nodesF=init_table(*boolVars); | ||
|  |       bVar2mVar=bVar2mVar_ex[i]; | ||
|  |       vars=vars_ex[i]; | ||
|  |        | ||
|  |       Forward(nodes_ex[i]); | ||
|  |       rootProb=GetOutsideExpe(nodes_ex[i],example_prob[i]); | ||
|  | 
 | ||
|  |       if (rootProb<=0.0) | ||
|  |         CLL = CLL + LOGZERO*example_prob[i]; | ||
|  |       else | ||
|  |         CLL = CLL + log(rootProb)*example_prob[i]; | ||
|  |        | ||
|  |       nodes_probs_ex[i]=rootProb; | ||
|  |       destroy_table(nodesB,*boolVars); | ||
|  |       destroy_table(nodesF,*boolVars); | ||
|  |     } | ||
|  |     else | ||
|  |       if (nodes_ex[i]==Cudd_ReadLogicZero(mgr_ex[i])) | ||
|  |         CLL=CLL+LOGZERO*example_prob[i]; | ||
|  |   } | ||
|  |   return CLL; | ||
|  | } | ||
|  | 
 | ||
|  | static int end(void) | ||
|  | { | ||
|  |   int r,i; | ||
|  | 
 | ||
|  |   for (i=0;i<ex;i++) | ||
|  |   { | ||
|  |     Cudd_Quit(mgr_ex[i]); | ||
|  |     free(bVar2mVar_ex[i]); | ||
|  |     free(vars_ex[i]); | ||
|  |     free(probs_ex[i]); | ||
|  |     fflush(stdout); | ||
|  |   } | ||
|  |    | ||
|  |   free(mgr_ex); | ||
|  |   free(bVar2mVar_ex); | ||
|  |   free(vars_ex); | ||
|  |   free(probs_ex); | ||
|  |   free(nVars_ex); | ||
|  |   free(boolVars_ex); | ||
|  |   free(nodes_probs_ex); | ||
|  |   for (r=0;r<nRules;r++) | ||
|  |   { | ||
|  |     for (i=0;i<rules[r]-1;i++) | ||
|  |     { | ||
|  |       free(eta[r][i]); | ||
|  |       free(eta_temp[r][i]); | ||
|  |     } | ||
|  |     free(eta[r]); | ||
|  |     free(eta_temp[r]); | ||
|  |   } | ||
|  |   free(eta); | ||
|  |   free(eta_temp); | ||
|  |   for (r=0;r<nRules;r++) | ||
|  |   { | ||
|  |     free(arrayprob[r]); | ||
|  |   } | ||
|  |   free(arrayprob); | ||
|  |   free(rules); | ||
|  | 
 | ||
|  |   return 1; | ||
|  | } | ||
|  | 
 | ||
|  | 
 | ||
|  | static int ret_prob(void) | ||
|  | { | ||
|  |   YAP_Term arg1,arg2,out; | ||
|  |   DdNode * node; | ||
|  |    | ||
|  |   arg1=YAP_ARG1; | ||
|  |   arg2=YAP_ARG2; | ||
|  |   node=(DdNode *)YAP_IntOfTerm(arg1); | ||
|  | 
 | ||
|  |   if (!Cudd_IsConstant(node)) | ||
|  |   { | ||
|  |     table=init_table(*boolVars); | ||
|  |     out=YAP_MkFloatTerm(Prob(node,0)); | ||
|  |     destroy_table(table,*boolVars); | ||
|  |   } | ||
|  |   else | ||
|  |   { | ||
|  |     if (node==Cudd_ReadOne(mgr)) | ||
|  |       out=YAP_MkFloatTerm(1.0); | ||
|  |     else   | ||
|  |       out=YAP_MkFloatTerm(0.0); | ||
|  |   } | ||
|  | 
 | ||
|  |   return(YAP_Unify(out,arg2)); | ||
|  | } | ||
|  | 
 | ||
|  | double Prob(DdNode *node,int comp_par) | ||
|  | /* compute the probability of the expression rooted at node.
 | ||
|  | table is used to store nodeB for which the probability has alread been computed | ||
|  | so that it is not recomputed | ||
|  |  */ | ||
|  | { | ||
|  |   int index,mVarIndex,comp,pos; | ||
|  |   variable v; | ||
|  |   double res; | ||
|  |   double p,pt,pf,BChild0,BChild1; | ||
|  |   double * value_p; | ||
|  |   DdNode *nodekey,*T,*F; | ||
|  | 
 | ||
|  |   comp=Cudd_IsComplement(node);    | ||
|  |   comp=(comp && !comp_par) ||(!comp && comp_par); | ||
|  |   if (Cudd_IsConstant(node)) | ||
|  |   { | ||
|  |     if (comp) | ||
|  |       return 0.0; | ||
|  |     else | ||
|  |       return 1.0; | ||
|  |   } | ||
|  |   else | ||
|  |   { | ||
|  |     nodekey=Cudd_Regular(node); | ||
|  | /*    if (comp)
 | ||
|  |       nodekey=Cudd_Complement(nodefw); | ||
|  |     else | ||
|  |       nodekey=nodefw;*/ | ||
|  |     value_p=get_value(table,nodekey); | ||
|  |     if (value_p!=NULL) | ||
|  |       return *value_p; | ||
|  |     else | ||
|  |     { | ||
|  |       index=Cudd_NodeReadIndex(node);  //Returns the index of the node. The node pointer can be either regular or complemented.
 | ||
|  |       //The index field holds the name of the variable that labels the node. The index of a variable is a permanent attribute that reflects the order of creation.
 | ||
|  |       p=probs[index]; | ||
|  |       T = Cudd_T(node); | ||
|  |       F = Cudd_E(node); | ||
|  |       pf=Prob(F,comp); | ||
|  |       pt=Prob(T,comp); | ||
|  |       BChild0=pf*(1-p); | ||
|  |       BChild1=pt*p; | ||
|  |       mVarIndex=bVar2mVar[index]; | ||
|  |       v=vars[mVarIndex];   | ||
|  |       pos=index-v.firstBoolVar; | ||
|  |       res=BChild0+BChild1; | ||
|  |       add_node(table,nodekey,res); | ||
|  |       return res; | ||
|  |     } | ||
|  |   } | ||
|  | } | ||
|  | 
 | ||
|  | 
 | ||
|  | 
 | ||
|  | static int add_var(void) | ||
|  | { | ||
|  |   YAP_Term arg1,arg2,arg3,arg4,out,probTerm,probTerm_temp; | ||
|  |   variable * v; | ||
|  |   int i; | ||
|  |   DdNode * node; | ||
|  |   double p,p0; | ||
|  | 
 | ||
|  | 
 | ||
|  |   arg1=YAP_ARG1; | ||
|  |   arg2=YAP_ARG2; | ||
|  |   arg3=YAP_ARG3;  | ||
|  |   arg4=YAP_ARG4; | ||
|  |   *nVars=*nVars+1; | ||
|  |   vars=(variable *) realloc(vars,*nVars * sizeof(variable)); | ||
|  |   v=&vars[*nVars-1]; | ||
|  |   v->nVal=YAP_IntOfTerm(arg1); | ||
|  |   v->nRule=YAP_IntOfTerm(arg3); | ||
|  |   v->firstBoolVar=*boolVars; | ||
|  |   probs=(double *) realloc(probs,(((*boolVars+v->nVal-1)* sizeof(double)))); | ||
|  |   bVar2mVar=(int *) realloc(bVar2mVar,((*boolVars+v->nVal-1)* sizeof(int))); | ||
|  |   probTerm=arg2;  | ||
|  |   p0=1; | ||
|  |   for (i=0;i<v->nVal-1;i++) | ||
|  |   { | ||
|  |     node=Cudd_bddIthVar(mgr,*boolVars+i); | ||
|  |     p=YAP_FloatOfTerm(YAP_HeadOfTerm(probTerm)); | ||
|  |     bVar2mVar[*boolVars+i]=*nVars-1; | ||
|  |     probs[*boolVars+i]=p/p0; | ||
|  |     probTerm_temp=YAP_TailOfTerm(probTerm); | ||
|  |     probTerm=probTerm_temp; | ||
|  |     p0=p0*(1-p/p0); | ||
|  |   } | ||
|  |   *boolVars=*boolVars+v->nVal-1; | ||
|  |   rules[v->nRule]= v->nVal;  | ||
|  |   out=YAP_MkIntTerm((YAP_Int)* nVars-1); | ||
|  |   return YAP_Unify(out,arg4); | ||
|  | } | ||
|  | 
 | ||
|  | static int equality(void) | ||
|  | { | ||
|  |   YAP_Term arg1,arg2,arg3,out; | ||
|  |   int varIndex; | ||
|  |   int value; | ||
|  |   int i; | ||
|  |   variable v; | ||
|  |   DdNode * node, * tmp,*var; | ||
|  | 
 | ||
|  |   arg1=YAP_ARG1; //var 
 | ||
|  |   arg2=YAP_ARG2; //value
 | ||
|  |   arg3=YAP_ARG3; //node
 | ||
|  |   varIndex=YAP_IntOfTerm(arg1); | ||
|  |   value=YAP_IntOfTerm(arg2); | ||
|  |   v=vars[varIndex]; | ||
|  |   i=v.firstBoolVar; | ||
|  |   tmp=Cudd_ReadOne(mgr); | ||
|  |   Cudd_Ref(tmp); | ||
|  |   node=NULL; | ||
|  |   for (i=v.firstBoolVar;i<v.firstBoolVar+value;i++) | ||
|  |   { | ||
|  |     var=Cudd_bddIthVar(mgr,i); | ||
|  |     node=Cudd_bddAnd(mgr,tmp,Cudd_Not(var)); | ||
|  |     Cudd_Ref(node); | ||
|  |     Cudd_RecursiveDeref(mgr,tmp); | ||
|  |     tmp=node; | ||
|  |   } | ||
|  |   if (!(value==v.nVal-1)) | ||
|  |   { | ||
|  |     var=Cudd_bddIthVar(mgr,v.firstBoolVar+value); | ||
|  |     node=Cudd_bddAnd(mgr,tmp,var); | ||
|  |     Cudd_Ref(node); | ||
|  |     Cudd_RecursiveDeref(mgr,tmp); | ||
|  |   } | ||
|  |   out=YAP_MkIntTerm((YAP_Int) node); | ||
|  |   return(YAP_Unify(out,arg3)); | ||
|  | } | ||
|  | 
 | ||
|  | static int one(void) | ||
|  | { | ||
|  |   YAP_Term arg,out; | ||
|  |   DdNode * node; | ||
|  | 
 | ||
|  |   arg=YAP_ARG1; | ||
|  |   node =  Cudd_ReadOne(mgr); | ||
|  |   Cudd_Ref(node); | ||
|  |   out=YAP_MkIntTerm((YAP_Int) node); | ||
|  |   return(YAP_Unify(out,arg)); | ||
|  | } | ||
|  | 
 | ||
|  | static int zero(void) | ||
|  | { | ||
|  |   YAP_Term arg,out; | ||
|  |   DdNode * node; | ||
|  | 
 | ||
|  |   arg=YAP_ARG1; | ||
|  |   node = Cudd_ReadLogicZero(mgr); | ||
|  |   Cudd_Ref(node); | ||
|  |   out=YAP_MkIntTerm((YAP_Int) node); | ||
|  |   return(YAP_Unify(out,arg)); | ||
|  | } | ||
|  | 
 | ||
|  | static int bdd_not(void) | ||
|  | { | ||
|  |   YAP_Term arg1,arg2,out; | ||
|  |   DdNode * node; | ||
|  |   arg1=YAP_ARG1; | ||
|  |   arg2=YAP_ARG2; | ||
|  | 
 | ||
|  |   node = (DdNode *)YAP_IntOfTerm(arg1); | ||
|  |   node=Cudd_Not(node); | ||
|  |   out=YAP_MkIntTerm((YAP_Int) node); | ||
|  |   return(YAP_Unify(out,arg2)); | ||
|  | } | ||
|  | 
 | ||
|  | static int and(void) | ||
|  | { | ||
|  |   YAP_Term arg1,arg2,arg3,out; | ||
|  |   DdNode * node1, *node2,*nodeout; | ||
|  | 
 | ||
|  |   arg1=YAP_ARG1; | ||
|  |   arg2=YAP_ARG2; | ||
|  |   arg3=YAP_ARG3; | ||
|  |   node1=(DdNode *)YAP_IntOfTerm(arg1); | ||
|  |   node2=(DdNode *)YAP_IntOfTerm(arg2); | ||
|  |   nodeout=Cudd_bddAnd(mgr,node1,node2); | ||
|  |   Cudd_Ref(nodeout); | ||
|  |   out=YAP_MkIntTerm((YAP_Int) nodeout); | ||
|  |   return(YAP_Unify(out,arg3)); | ||
|  | } | ||
|  | 
 | ||
|  | static int or(void) | ||
|  | { | ||
|  |   YAP_Term arg1,arg2,arg3,out; | ||
|  |   DdNode * node1,*node2,*nodeout; | ||
|  | 
 | ||
|  |   arg1=YAP_ARG1; | ||
|  |   arg2=YAP_ARG2; | ||
|  |   arg3=YAP_ARG3; | ||
|  |   node1=(DdNode *)YAP_IntOfTerm(arg1); | ||
|  |   node2=(DdNode *)YAP_IntOfTerm(arg2); | ||
|  |   nodeout=Cudd_bddOr(mgr,node1,node2); | ||
|  |   Cudd_Ref(nodeout); | ||
|  |   out=YAP_MkIntTerm((YAP_Int) nodeout); | ||
|  |   return(YAP_Unify(out,arg3)); | ||
|  | } | ||
|  | 
 | ||
|  | static int garbage_collect(void) | ||
|  | { | ||
|  |   YAP_Term arg1,arg2,out; | ||
|  |   YAP_Int nodes,clearCache; | ||
|  | 
 | ||
|  |   arg1=YAP_ARG1; | ||
|  |   arg2=YAP_ARG2; | ||
|  |   clearCache=YAP_IntOfTerm(arg1); | ||
|  |   nodes=(YAP_Int)cuddGarbageCollect(mgr,clearCache); | ||
|  |   out=YAP_MkIntTerm(nodes); | ||
|  |   return(YAP_Unify(out,arg2)); | ||
|  | } | ||
|  | 
 | ||
|  | static int bdd_to_add(void) | ||
|  | { | ||
|  |   YAP_Term arg1,arg2,out; | ||
|  |   DdNode * node1,*node2; | ||
|  | 
 | ||
|  |   arg1=YAP_ARG1; | ||
|  |   arg2=YAP_ARG2; | ||
|  |   node1=(DdNode *)YAP_IntOfTerm(arg1); | ||
|  |   node2= Cudd_BddToAdd(mgr,node1); | ||
|  |   out=YAP_MkIntTerm((YAP_Int) node2); | ||
|  |   return(YAP_Unify(out,arg2)); | ||
|  | } | ||
|  | 
 | ||
|  | static int create_dot(void) | ||
|  | { | ||
|  |   char * onames[]={"Out"}; | ||
|  |   char ** inames; | ||
|  |    DdNode * array[1]; | ||
|  |   YAP_Term arg1,arg2; | ||
|  |   int i,b,index; | ||
|  |   variable v; | ||
|  |   char numberVar[10],numberBit[10],filename[1000]; | ||
|  |   FILE * file; | ||
|  |    | ||
|  |   arg1=YAP_ARG1; | ||
|  |   arg2=YAP_ARG2; | ||
|  | 
 | ||
|  |   YAP_StringToBuffer(arg2,filename,1000); | ||
|  |   inames= (char **) malloc(sizeof(char *)*(*boolVars)); | ||
|  |   index=0; | ||
|  |   for (i=0;i<*nVars;i++) | ||
|  |   { | ||
|  |     v=vars[i]; | ||
|  |     for (b=0;b<v.nVal-1;b++) | ||
|  |     {   | ||
|  |       inames[b+index]=(char *) malloc(sizeof(char)*20); | ||
|  |       strcpy(inames[b+index],"X"); | ||
|  |       sprintf(numberVar,"%d",i); | ||
|  |       strcat(inames[b+index],numberVar); | ||
|  |       strcat(inames[b+index],"_"); | ||
|  |       sprintf(numberBit,"%d",b); | ||
|  |       strcat(inames[b+index],numberBit); | ||
|  |     } | ||
|  |     index=index+v.nVal-1; | ||
|  |   } | ||
|  |   array[0]=(DdNode *)YAP_IntOfTerm(arg1); | ||
|  |   file = open_file(filename, "w"); | ||
|  |   Cudd_DumpDot(mgr,1,array,inames,onames,file); | ||
|  |   fclose(file); | ||
|  |   index=0; | ||
|  |   for (i=0;i<*nVars;i++) | ||
|  |   { | ||
|  |     v=vars[i]; | ||
|  |     for (b=0;b<v.nVal-1;b++) | ||
|  |     {   | ||
|  |       free(inames[b+index]); | ||
|  |     } | ||
|  |     index=index+v.nVal-1; | ||
|  |   } | ||
|  |   free(inames); | ||
|  |   return 1; | ||
|  | } | ||
|  | 
 | ||
|  | 
 | ||
|  | static int rec_deref(void) | ||
|  | { | ||
|  |   YAP_Term arg1; | ||
|  |   DdNode * node; | ||
|  | 
 | ||
|  |   arg1=YAP_ARG1; | ||
|  |   node=(DdNode *) YAP_IntOfTerm(arg1); | ||
|  |   Cudd_RecursiveDeref(mgr, node); | ||
|  |   return 1; | ||
|  | } | ||
|  | 
 | ||
|  | 
 | ||
|  | 
 | ||
|  | double ProbPath(DdNode *node,int comp_par) | ||
|  | { | ||
|  |   int index,mVarIndex,comp,pos,position,boolVarIndex; | ||
|  |   variable v; | ||
|  |   double res; | ||
|  |   double value,p,pt,pf,BChild0,BChild1,e0,e1; | ||
|  |   double * value_p,** eta_rule; | ||
|  |   DdNode *nodekey,*T,*F; | ||
|  | 
 | ||
|  |   comp=Cudd_IsComplement(node);    | ||
|  |   comp=(comp && !comp_par) ||(!comp && comp_par); | ||
|  |   if (Cudd_IsConstant(node)) | ||
|  |   { | ||
|  |     value=Cudd_V(node); | ||
|  |     if (comp) | ||
|  |     { | ||
|  |       return 0.0; | ||
|  |     } | ||
|  |     else | ||
|  |     { | ||
|  |       return 1.0; | ||
|  |     } | ||
|  |   } | ||
|  |   else | ||
|  |   { | ||
|  |     nodekey=Cudd_Regular(node); | ||
|  |     value_p=get_value(nodesB,nodekey); | ||
|  |     if (value_p!=NULL) | ||
|  |     { | ||
|  |       return *value_p; | ||
|  |     } | ||
|  |     else | ||
|  |     { | ||
|  |       index=Cudd_NodeReadIndex(node); | ||
|  |       p=probs[index]; | ||
|  |       T = Cudd_T(node); | ||
|  |       F = Cudd_E(node); | ||
|  |       pf=ProbPath(F,comp); | ||
|  |       pt=ProbPath(T,comp); | ||
|  |       BChild0=pf*(1-p); | ||
|  |       BChild1=pt*p; | ||
|  |       value_p=get_value(nodesF,nodekey); | ||
|  |       e0 = (*value_p)*BChild0;  | ||
|  |       e1 = (*value_p)*BChild1;  | ||
|  |       mVarIndex=bVar2mVar[index]; | ||
|  |       v=vars[mVarIndex];   | ||
|  |       pos=index-v.firstBoolVar; | ||
|  |       eta_rule=eta_temp[v.nRule]; | ||
|  |       eta_rule[pos][0]=eta_rule[pos][0]+e0; | ||
|  |       eta_rule[pos][1]=eta_rule[pos][1]+e1; | ||
|  |       res=BChild0+BChild1; | ||
|  |       add_node(nodesB,nodekey,res); | ||
|  |       position=Cudd_ReadPerm(mgr,index); | ||
|  |       position=position+1; | ||
|  |       boolVarIndex=Cudd_ReadInvPerm(mgr,position);  //Returns the index of the variable currently in the i-th position of the order. 
 | ||
|  |       if (position<*boolVars) | ||
|  |       { | ||
|  |         sigma[position]=sigma[position]+e0+e1; | ||
|  |       } | ||
|  |       if(!Cudd_IsConstant(T)) | ||
|  |       { | ||
|  |         index=Cudd_NodeReadIndex(T);   | ||
|  |         position=Cudd_ReadPerm(mgr,index); | ||
|  |         sigma[position]=sigma[position]-e1; | ||
|  |       } | ||
|  |        | ||
|  |       if(!Cudd_IsConstant(F)) | ||
|  |       { | ||
|  |         index=Cudd_NodeReadIndex(F); | ||
|  |         position=Cudd_ReadPerm(mgr,index); | ||
|  |         sigma[position]=sigma[position]-e0; | ||
|  |       } | ||
|  |      | ||
|  |       return res; | ||
|  |     } | ||
|  |   } | ||
|  | } | ||
|  | 
 | ||
|  | 
 | ||
|  | 
 | ||
|  | 
 | ||
|  | void Forward(DdNode *root) | ||
|  | { | ||
|  |   int i,j; | ||
|  | 
 | ||
|  |   if (*boolVars) | ||
|  |   { | ||
|  |     nodesToVisit= (DdNode ***)malloc(sizeof(DdNode **)* *boolVars); | ||
|  |     NnodesToVisit= (int *)malloc(sizeof(int)* *boolVars); | ||
|  |     nodesToVisit[0]=(DdNode **)malloc(sizeof(DdNode *));  | ||
|  |     nodesToVisit[0][0]=root; | ||
|  |     NnodesToVisit[0]=1; | ||
|  |     for(i=1;i<*boolVars;i++) | ||
|  |     { | ||
|  |       nodesToVisit[i]=NULL; | ||
|  |       NnodesToVisit[i]=0; | ||
|  |     } | ||
|  |     add_node(nodesF,Cudd_Regular(root),1); | ||
|  |     for(i=0;i<*boolVars;i++) | ||
|  |     { | ||
|  |       for(j=0;j<NnodesToVisit[i];j++) | ||
|  |       UpdateForward(nodesToVisit[i][j]); | ||
|  |     } | ||
|  |     for(i=0;i<*boolVars;i++) | ||
|  |     { | ||
|  |       free(nodesToVisit[i]); | ||
|  |     } | ||
|  |     free(nodesToVisit); | ||
|  |     free(NnodesToVisit); | ||
|  |   } | ||
|  |   else | ||
|  |   { | ||
|  |     add_node(nodesF,Cudd_Regular(root),1); | ||
|  |   } | ||
|  | } | ||
|  | 
 | ||
|  | void UpdateForward(DdNode *node) | ||
|  | { | ||
|  |   int index,position,mVarIndex; | ||
|  |   DdNode *T,*E,*nodereg; | ||
|  |   variable v; | ||
|  |   double *value_p,*value_p_T,*value_p_F,p; | ||
|  | 
 | ||
|  |   if (Cudd_IsConstant(node))  | ||
|  |   { | ||
|  |     return; | ||
|  |   } | ||
|  |   else | ||
|  |   { | ||
|  |     index=Cudd_NodeReadIndex(node); | ||
|  |     mVarIndex=bVar2mVar[index]; | ||
|  |     v=vars[mVarIndex]; | ||
|  |     p=probs[index]; | ||
|  |     nodereg=Cudd_Regular(node); | ||
|  |     value_p=get_value(nodesF,nodereg); | ||
|  |     if (value_p== NULL) | ||
|  |     { | ||
|  |       printf("Error\n"); | ||
|  |       return; | ||
|  |     } | ||
|  |     else | ||
|  |     { | ||
|  |       T = Cudd_T(node); | ||
|  |       E = Cudd_E(node); | ||
|  |       if (!Cudd_IsConstant(T))  | ||
|  |       { | ||
|  |         value_p_T=get_value(nodesF,T); | ||
|  |         if (value_p_T!= NULL) | ||
|  |         { | ||
|  |            *value_p_T= *value_p_T+*value_p*p; | ||
|  |         } | ||
|  |         else | ||
|  |         { | ||
|  |           add_or_replace_node(nodesF,Cudd_Regular(T),*value_p*p); | ||
|  |           index=Cudd_NodeReadIndex(T); | ||
|  |           position=Cudd_ReadPerm(mgr,index); | ||
|  |           nodesToVisit[position]=(DdNode **)realloc(nodesToVisit[position], | ||
|  | 	    (NnodesToVisit[position]+1)* sizeof(DdNode *)); | ||
|  |           nodesToVisit[position][NnodesToVisit[position]]=T; | ||
|  |           NnodesToVisit[position]=NnodesToVisit[position]+1; | ||
|  |         } | ||
|  |       } | ||
|  |       if (!Cudd_IsConstant(E))  | ||
|  |       { | ||
|  |         value_p_F=get_value(nodesF,Cudd_Regular(E)); | ||
|  | 
 | ||
|  |         if (value_p_F!= NULL) | ||
|  |         { | ||
|  |           *value_p_F= *value_p_F+*value_p*(1-p); | ||
|  |         } | ||
|  |         else | ||
|  |         { | ||
|  |           add_or_replace_node(nodesF,Cudd_Regular(E),*value_p*(1-p)); | ||
|  |           index=Cudd_NodeReadIndex(E); | ||
|  |           position=Cudd_ReadPerm(mgr,index); | ||
|  |           nodesToVisit[position]=(DdNode **)realloc(nodesToVisit[position], | ||
|  | 	    (NnodesToVisit[position]+1)* sizeof(DdNode *)); | ||
|  |           nodesToVisit[position][NnodesToVisit[position]]=E; | ||
|  |           NnodesToVisit[position]=NnodesToVisit[position]+1; | ||
|  |         } | ||
|  |       } | ||
|  |       return; | ||
|  |     } | ||
|  |   } | ||
|  | } | ||
|  | 
 | ||
|  | 
 | ||
|  | int indexMvar(DdNode * node) | ||
|  | { | ||
|  |   int index,mVarIndex; | ||
|  | 
 | ||
|  |   index=Cudd_NodeReadIndex(node); | ||
|  |   mVarIndex=bVar2mVar[index]; | ||
|  |   return mVarIndex; | ||
|  | } | ||
|  | 
 | ||
|  | 
 | ||
|  | 
 | ||
|  | double GetOutsideExpe(DdNode *root,double ex_prob)   | ||
|  | { | ||
|  |   int i,j,mVarIndex,bVarIndex; | ||
|  |   double **eta_rule; | ||
|  |   double theta,rootProb, T=0; | ||
|  | 
 | ||
|  | 
 | ||
|  |   sigma=(double *)malloc(*boolVars * sizeof(double)); | ||
|  | 
 | ||
|  |   for (j=0; j<*boolVars; j++) | ||
|  |   { | ||
|  |     sigma[j]=0; | ||
|  |   } | ||
|  |   for (j=0; j<nRules; j++) | ||
|  |   { | ||
|  |     for (i=0; i<rules[j]-1; i++) | ||
|  |     { | ||
|  |       eta_temp[j][i][0]=0; | ||
|  |       eta_temp[j][i][1]=0; | ||
|  |     } | ||
|  |   } | ||
|  |   rootProb=ProbPath(root,0); | ||
|  |   if (rootProb>0.0) | ||
|  |   { | ||
|  |     for (j=0; j<*boolVars; j++) | ||
|  |     { | ||
|  |       T += sigma[j]; | ||
|  |       bVarIndex=Cudd_ReadInvPerm(mgr,j); | ||
|  |       if (bVarIndex==-1)   | ||
|  |       { | ||
|  |         bVarIndex=j; | ||
|  |       } | ||
|  | 
 | ||
|  |       mVarIndex=bVar2mVar[bVarIndex]; | ||
|  |       eta_rule=eta_temp[vars[mVarIndex].nRule]; | ||
|  |       for (i=0; i<vars[mVarIndex].nVal-1;i++) | ||
|  |       { | ||
|  |         theta=probs[bVarIndex]; | ||
|  |         eta_rule[i][0]=eta_rule[i][0]+T*(1-theta); | ||
|  |         eta_rule[i][1]=eta_rule[i][1]+T*theta; | ||
|  |       }    | ||
|  |     } | ||
|  | 
 | ||
|  |     for (j=0; j<nRules; j++) | ||
|  |     { | ||
|  |       for (i=0; i<rules[j]-1; i++) | ||
|  |       { | ||
|  |         eta[j][i][0]=eta[j][i][0]+eta_temp[j][i][0]*ex_prob/rootProb; | ||
|  |         eta[j][i][1]=eta[j][i][1]+eta_temp[j][i][1]*ex_prob/rootProb; | ||
|  |       } | ||
|  |     } | ||
|  |   } | ||
|  |   free(sigma); | ||
|  |   return rootProb; | ||
|  | } | ||
|  | 
 | ||
|  | 
 | ||
|  | void Maximization(void) | ||
|  | { | ||
|  |   int r,i,j,e; | ||
|  |   double sum=0; | ||
|  |   double *probs_rule,**eta_rule;   | ||
|  | 
 | ||
|  |   for (r=0;r<nRules;r++) | ||
|  |   { | ||
|  |     eta_rule=eta[r]; | ||
|  |     for (i=0;i<rules[r]-1;i++) | ||
|  |     { | ||
|  |       sum=(eta_rule[i][0]+eta_rule[i][1]); | ||
|  |       if (sum==0.0) | ||
|  |       { | ||
|  |         arrayprob[r][i]=0; | ||
|  |       } | ||
|  |       else  | ||
|  |         arrayprob[r][i]=eta_rule[i][1]/sum;     | ||
|  |     } | ||
|  |   } | ||
|  | 
 | ||
|  |   for(e=0;e<ex;e++) | ||
|  |   { | ||
|  |     nVars=nVars_ex+e; | ||
|  |     probs=probs_ex[e]; | ||
|  |     vars=vars_ex[e]; | ||
|  | 
 | ||
|  |     for (j=0;j<*nVars;j++) | ||
|  |     { | ||
|  |       r=vars[j].nRule; | ||
|  |       probs_rule=arrayprob[r]; | ||
|  |       for(i=0;i<rules[r]-1;i++) | ||
|  |       {     | ||
|  |         probs[vars[j].firstBoolVar+i]=probs_rule[i];      | ||
|  |       } | ||
|  |     } | ||
|  |   } | ||
|  | } | ||
|  | 
 | ||
|  | static int randomize(void) | ||
|  | { | ||
|  |   int i,j,e,rule; | ||
|  |   double * theta,p0; | ||
|  |   double pmass,par; | ||
|  |   double **Theta_rules; | ||
|  |    | ||
|  |   Theta_rules=(double **)malloc(nRules *sizeof(double *)); | ||
|  | 
 | ||
|  |   for (j=0;j<nRules;j++) | ||
|  |   { | ||
|  |     Theta_rules[j]=(double *)malloc(rules[j]*sizeof(double)); | ||
|  |   } | ||
|  | 
 | ||
|  |   for (j=0;j<nRules;j++) | ||
|  |   { | ||
|  |     theta=Theta_rules[j]; | ||
|  |     pmass=0; | ||
|  |     for (i=0;i<rules[j]-1;i++) | ||
|  |     { | ||
|  |       par=((double)rand())/RAND_MAX*(1-pmass); | ||
|  |       pmass=pmass+par; | ||
|  |       theta[i]=par; | ||
|  |     } | ||
|  |     theta[rules[j]-1]=1-pmass; | ||
|  |   } | ||
|  |   for(e=0;e<ex;e++) | ||
|  |   { | ||
|  |     nVars=nVars_ex+e; | ||
|  |     probs=probs_ex[e]; | ||
|  |     vars=vars_ex[e]; | ||
|  |     for (j=0; j<*nVars; j++) | ||
|  |     { | ||
|  |       rule=vars[j].nRule; | ||
|  |       theta=Theta_rules[rule]; | ||
|  |       p0=1; | ||
|  |       for (i=0; i<vars[j].nVal-1;i++)   | ||
|  |       {     | ||
|  |         probs[vars[j].firstBoolVar+i]=theta[i]/p0; | ||
|  |         p0=p0*(1-theta[i]/p0); | ||
|  |       } | ||
|  |     } | ||
|  |   } | ||
|  |   for (j=0;j<nRules;j++) | ||
|  |   { | ||
|  |     free(Theta_rules[j]); | ||
|  |   } | ||
|  |   free(Theta_rules); | ||
|  |   return 1; | ||
|  | } | ||
|  | 
 | ||
|  | static int EM(void) | ||
|  | { | ||
|  |   YAP_Term arg1,arg2,arg3,arg4,arg5,arg6,arg7, | ||
|  |     out1,out2,nodesTerm,ruleTerm,tail,pair,compoundTerm; | ||
|  |   DdNode * node1,**nodes_ex; | ||
|  |   int r,lenNodes,i,iter; | ||
|  |   long iter1; | ||
|  |   double CLL0= -2.2*pow(10,10); //-inf
 | ||
|  |   double CLL1= -1.7*pow(10,8);  //+inf   
 | ||
|  |   double p,p0,**eta_rule,ea,er;  | ||
|  |   double ratio,diff; | ||
|  | 
 | ||
|  |   arg1=YAP_ARG1; | ||
|  |   arg2=YAP_ARG2; | ||
|  |   arg3=YAP_ARG3; | ||
|  |   arg4=YAP_ARG4; | ||
|  |   arg5=YAP_ARG5; | ||
|  |   arg6=YAP_ARG6; | ||
|  |   arg7=YAP_ARG7; | ||
|  | 
 | ||
|  |   nodesTerm=arg1;  | ||
|  |   ea=YAP_FloatOfTerm(arg2); | ||
|  |   er=YAP_FloatOfTerm(arg3); | ||
|  |   lenNodes=YAP_IntOfTerm(arg4);   | ||
|  |   iter=YAP_IntOfTerm(arg5);   | ||
|  | 
 | ||
|  |   nodes_ex=(DdNode **)malloc(lenNodes*sizeof(DdNode*)); | ||
|  |   nodes_probs_ex=(double *)malloc(lenNodes*sizeof(double)); | ||
|  |   example_prob=(double *)malloc(lenNodes*sizeof(double)); | ||
|  | 
 | ||
|  |   for (i=0;i<lenNodes;i++) | ||
|  |   { | ||
|  |     pair=YAP_HeadOfTerm(nodesTerm); | ||
|  |     node1=(DdNode *)YAP_IntOfTerm(YAP_HeadOfTerm(pair)); | ||
|  |     nodes_ex[i]=node1; | ||
|  |     pair=YAP_TailOfTerm(pair); | ||
|  |     example_prob[i]=YAP_FloatOfTerm(YAP_HeadOfTerm(pair)); | ||
|  |     nodesTerm=YAP_TailOfTerm(nodesTerm); | ||
|  |   } | ||
|  |   diff=CLL1-CLL0; | ||
|  |   ratio=diff/fabs(CLL0); | ||
|  |   if (iter==-1) | ||
|  |     iter1= 2147000000; | ||
|  |   else iter1=iter; | ||
|  |    | ||
|  | 
 | ||
|  |   while  ( (diff>ea) && (ratio>er) && (cycle<iter1) ) | ||
|  |   { | ||
|  |     cycle++; | ||
|  |     for (r=0;r<nRules;r++) | ||
|  |     { | ||
|  |       for (i=0;i<rules[r]-1;i++)   | ||
|  |       { | ||
|  |         eta_rule=eta[r]; | ||
|  |         eta_rule[i][0]=0; | ||
|  |         eta_rule[i][1]=0; | ||
|  |       } | ||
|  |     } | ||
|  |     CLL0 = CLL1; | ||
|  |     CLL1 = Expectation(nodes_ex,lenNodes); | ||
|  |     Maximization(); | ||
|  |     diff=CLL1-CLL0; | ||
|  |     ratio=diff/fabs(CLL0); | ||
|  |   } | ||
|  |   out2= YAP_TermNil(); | ||
|  |   for (r=0; r<nRules; r++) | ||
|  |   { | ||
|  |     tail=YAP_TermNil(); | ||
|  |     p0=1; | ||
|  |     for (i=0;i<rules[r]-1;i++)   | ||
|  |     { | ||
|  |       p=arrayprob[r][i]*p0; | ||
|  |       tail=YAP_MkPairTerm(YAP_MkFloatTerm(p),tail); | ||
|  |       p0=p0*(1-arrayprob[r][i]);  | ||
|  |     } | ||
|  |     tail=YAP_MkPairTerm(YAP_MkFloatTerm(p0),tail);   | ||
|  |     ruleTerm=YAP_MkIntTerm(r); | ||
|  |     compoundTerm=YAP_MkPairTerm(ruleTerm,YAP_MkPairTerm(tail,YAP_TermNil())); | ||
|  |     out2=YAP_MkPairTerm(compoundTerm,out2); | ||
|  |   } | ||
|  | 
 | ||
|  |   out1=YAP_MkFloatTerm(CLL1); | ||
|  |   YAP_Unify(out1,arg6); | ||
|  |   free(nodes_ex); | ||
|  |   free(example_prob); | ||
|  | 
 | ||
|  |   return (YAP_Unify(out2,arg7)); | ||
|  | } | ||
|  | 
 | ||
|  | static int Q(void) | ||
|  | { | ||
|  |   YAP_Term arg1,arg2,arg3,arg4,out,out1, | ||
|  |     term,nodesTerm,ruleTerm,tail,pair,compoundTerm; | ||
|  |   DdNode * node1,**nodes_ex; | ||
|  |   int r,lenNodes,i; | ||
|  |   double p1,p0,**eta_rule,CLL;  | ||
|  | 
 | ||
|  |   arg1=YAP_ARG1; | ||
|  |   arg2=YAP_ARG2; | ||
|  |   arg3=YAP_ARG3; | ||
|  |   arg4=YAP_ARG4; | ||
|  | 
 | ||
|  |   nodesTerm=arg1;  | ||
|  |   lenNodes=YAP_IntOfTerm(arg2);   | ||
|  | 
 | ||
|  |   nodes_ex=(DdNode **)malloc(lenNodes*sizeof(DdNode*)); | ||
|  |   example_prob=(double *)malloc(lenNodes*sizeof(double)); | ||
|  | 
 | ||
|  |   for (i=0;i<lenNodes;i++) | ||
|  |   { | ||
|  |     pair=YAP_HeadOfTerm(nodesTerm); | ||
|  |     node1=(DdNode *)YAP_IntOfTerm(YAP_HeadOfTerm(pair)); | ||
|  |     nodes_ex[i]=node1; | ||
|  |     pair=YAP_TailOfTerm(pair); | ||
|  |     example_prob[i]=YAP_FloatOfTerm(YAP_HeadOfTerm(pair)); | ||
|  |     nodesTerm=YAP_TailOfTerm(nodesTerm); | ||
|  |   } | ||
|  | 
 | ||
|  |   for (r=0;r<nRules;r++) | ||
|  |   { | ||
|  |     for (i=0;i<rules[r]-1;i++)   | ||
|  |     { | ||
|  |       eta_rule=eta[r]; | ||
|  |       eta_rule[i][0]=0; | ||
|  |       eta_rule[i][1]=0; | ||
|  |     } | ||
|  |   } | ||
|  |   CLL=Expectation(nodes_ex,lenNodes); | ||
|  |   out= YAP_TermNil(); | ||
|  | 
 | ||
|  |   for (r=0; r<nRules; r++) | ||
|  |   { | ||
|  |     tail=YAP_TermNil(); | ||
|  |     eta_rule=eta[r];     | ||
|  |     for (i=0;i<rules[r]-1;i++)   | ||
|  |     { | ||
|  |       p0=eta_rule[i][0]; | ||
|  |       p1=eta_rule[i][1]; | ||
|  |       term=YAP_MkPairTerm(YAP_MkFloatTerm(p0), | ||
|  |         YAP_MkPairTerm(YAP_MkFloatTerm(p1),YAP_TermNil())); | ||
|  |       tail=YAP_MkPairTerm(term,tail);     | ||
|  |     } | ||
|  | 
 | ||
|  |     ruleTerm=YAP_MkIntTerm(r); | ||
|  |     compoundTerm=YAP_MkPairTerm(ruleTerm,YAP_MkPairTerm(tail,YAP_TermNil())); | ||
|  |     out=YAP_MkPairTerm(compoundTerm,out); | ||
|  |   } | ||
|  | 
 | ||
|  |   free(nodes_ex); | ||
|  |   free(example_prob); | ||
|  | 
 | ||
|  |   out1=YAP_MkFloatTerm(CLL); | ||
|  |   YAP_Unify(out1,arg4); | ||
|  |   return (YAP_Unify(out,arg3)); | ||
|  | } | ||
|  | 
 | ||
|  | static int paths_to_non_zero(void) | ||
|  | { | ||
|  |   double paths; | ||
|  |   YAP_Term arg1,arg2,out; | ||
|  |   DdNode * node; | ||
|  | 
 | ||
|  |   arg1=YAP_ARG1; | ||
|  |   arg2=YAP_ARG2; | ||
|  |   node=(DdNode *)YAP_IntOfTerm(arg1); | ||
|  |   paths=Cudd_CountPathsToNonZero(node); | ||
|  |   out=YAP_MkFloatTerm(paths); | ||
|  |   return(YAP_Unify(out,arg2)); | ||
|  | } | ||
|  | 
 | ||
|  | static int paths(void) | ||
|  | { | ||
|  |   double paths; | ||
|  |   YAP_Term arg1,arg2,out; | ||
|  |   DdNode * node; | ||
|  | 
 | ||
|  |   arg1=YAP_ARG1; | ||
|  |   arg2=YAP_ARG2; | ||
|  |   node=(DdNode *)YAP_IntOfTerm(arg1); | ||
|  |   paths=Cudd_CountPath(node); | ||
|  |   out=YAP_MkFloatTerm(paths); | ||
|  |   return(YAP_Unify(out,arg2)); | ||
|  | } | ||
|  | 
 | ||
|  | static int dag_size(void) | ||
|  | { | ||
|  |   int size; | ||
|  |   YAP_Term arg1,arg2,out; | ||
|  |   DdNode * node; | ||
|  | 
 | ||
|  |   arg1=YAP_ARG1; | ||
|  |   arg2=YAP_ARG2; | ||
|  |   node=(DdNode *)YAP_IntOfTerm(arg1); | ||
|  |   size=Cudd_DagSize(node); | ||
|  |   out=YAP_MkIntTerm(size); | ||
|  |   return(YAP_Unify(out,arg2)); | ||
|  | } | ||
|  | 
 | ||
|  | void init_my_predicates() | ||
|  | /* function required by YAP for intitializing the predicates defined by a C function*/ | ||
|  | { | ||
|  |   YAP_UserCPredicate("init",init,2); | ||
|  |   YAP_UserCPredicate("init_bdd",init_bdd,0); | ||
|  |   YAP_UserCPredicate("end",end,0); | ||
|  |   YAP_UserCPredicate("end_bdd",end_bdd,0); | ||
|  |   YAP_UserCPredicate("add_var",add_var,4); | ||
|  |   YAP_UserCPredicate("equality",equality,3); | ||
|  |   YAP_UserCPredicate("and",and,3); | ||
|  |   YAP_UserCPredicate("one",one,1); | ||
|  |   YAP_UserCPredicate("zero",zero,1); | ||
|  |   YAP_UserCPredicate("or",or,3); | ||
|  |   YAP_UserCPredicate("bdd_not",bdd_not,2); | ||
|  |   YAP_UserCPredicate("create_dot",create_dot,2); | ||
|  |   YAP_UserCPredicate("init_test",init_test,1); | ||
|  |   YAP_UserCPredicate("end_test",end_test,0); | ||
|  |   YAP_UserCPredicate("ret_prob",ret_prob,2); | ||
|  |   YAP_UserCPredicate("em",EM,7); | ||
|  |   YAP_UserCPredicate("q",Q,4); | ||
|  |   YAP_UserCPredicate("randomize",randomize,0); | ||
|  |   YAP_UserCPredicate("deref",rec_deref,1); | ||
|  |   YAP_UserCPredicate("garbage_collect",garbage_collect,2); | ||
|  |   YAP_UserCPredicate("bdd_to_add",bdd_to_add,2); | ||
|  |   YAP_UserCPredicate("paths_to_non_zero",paths_to_non_zero,2); | ||
|  |   YAP_UserCPredicate("paths",paths,2); | ||
|  |   YAP_UserCPredicate("dag_size",dag_size,2); | ||
|  | } | ||
|  | FILE * open_file(char *filename, const char *mode) | ||
|  | /* opens a file */ | ||
|  | { | ||
|  |   FILE *fp; | ||
|  | 
 | ||
|  |   if ((fp = fopen(filename, mode)) == NULL)  | ||
|  |   { | ||
|  |     perror(filename); | ||
|  |     exit(1); | ||
|  |   } | ||
|  |   return fp; | ||
|  | } | ||
|  | 
 | ||
|  | 
 | ||
|  | tablerow* init_table(int varcnt) { | ||
|  |   int i; | ||
|  |   tablerow *tab; | ||
|  | 
 | ||
|  |   tab = (tablerow *) malloc(sizeof(rowel) * varcnt); | ||
|  |   for (i = 0; i < varcnt; i++)  | ||
|  |   { | ||
|  |     tab[i].row = NULL; | ||
|  |     tab[i].cnt = 0; | ||
|  |   } | ||
|  |   return tab; | ||
|  | } | ||
|  | 
 | ||
|  | 
 | ||
|  | void add_node(tablerow *tab, DdNode *node, double value) { | ||
|  |   int index = Cudd_NodeReadIndex(node); | ||
|  |    | ||
|  |   tab[index].row = (rowel *) realloc(tab[index].row,  | ||
|  |     (tab[index].cnt + 1) * sizeof(rowel)); | ||
|  |   tab[index].row[tab[index].cnt].key = node; | ||
|  |   tab[index].row[tab[index].cnt].value = value; | ||
|  |   tab[index].cnt += 1; | ||
|  | } | ||
|  | 
 | ||
|  | void add_or_replace_node(tablerow *tab, DdNode *node, double value) | ||
|  | { | ||
|  |   int i; | ||
|  |   int index = Cudd_NodeReadIndex(node); | ||
|  |   for(i = 0; i < tab[index].cnt; i++)  | ||
|  |   { | ||
|  |     if (tab[index].row[i].key == node)  | ||
|  |     { | ||
|  |       tab[index].row[i].value=value; | ||
|  |       return; | ||
|  |     } | ||
|  |   } | ||
|  |   tab[index].row = (rowel *) realloc(tab[index].row,  | ||
|  |     (tab[index].cnt + 1) * sizeof(rowel)); | ||
|  |   tab[index].row[tab[index].cnt].key = node; | ||
|  |   tab[index].row[tab[index].cnt].value = value; | ||
|  |   tab[index].cnt += 1; | ||
|  | } | ||
|  | 
 | ||
|  | double * get_value(tablerow *tab,  DdNode *node) { | ||
|  |   int i; | ||
|  |   int index = Cudd_NodeReadIndex(node); | ||
|  | 
 | ||
|  |   for(i = 0; i < tab[index].cnt; i++)  | ||
|  |   { | ||
|  |     if (tab[index].row[i].key == node) | ||
|  |     { | ||
|  |       return &tab[index].row[i].value; | ||
|  |     } | ||
|  |   } | ||
|  |   return NULL; | ||
|  | } | ||
|  | 
 | ||
|  | void destroy_table(tablerow *tab,int varcnt) | ||
|  | { | ||
|  |   int i; | ||
|  | 
 | ||
|  |   for (i = 0; i < varcnt; i++)  | ||
|  |   { | ||
|  |     free(tab[i].row); | ||
|  |   } | ||
|  |   free(tab); | ||
|  | } |