210 lines
		
	
	
		
			4.5 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
		
		
			
		
	
	
			210 lines
		
	
	
		
			4.5 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
|   | /*
 | ||
|  | 	LPAD and CP-Logic interpreter | ||
|  | 	 | ||
|  | Copyright (c) 2007, Fabrizio Riguzzi | ||
|  | 
 | ||
|  | This package uses the library cudd, see http://vlsi.colorado.edu/~fabio/CUDD/
 | ||
|  | for the relative license. | ||
|  | 
 | ||
|  | 
 | ||
|  | 	This file contains the definition of Prob and ProbBool plus the functions | ||
|  | 	for building the BDD | ||
|  | */ | ||
|  | 
 | ||
|  | 
 | ||
|  | #include "cplint.h"
 | ||
|  | #include <stdlib.h>
 | ||
|  | 
 | ||
|  | int correctPosition(int index,variable v, DdNode * node,int posBVar); | ||
|  | 
 | ||
|  | 
 | ||
|  | 
 | ||
|  | DdNode * retFunction(DdManager * mgr,array_t *expression, array_t *v) | ||
|  | /* given an expression term1+term2+...+termn, returns the BDD that implements that function */   | ||
|  | { | ||
|  |   array_t * term; | ||
|  |   DdNode * tNode, * tmp, *tmp1; | ||
|  |   int i; | ||
|  |    | ||
|  |   i=0; | ||
|  |   tNode=Cudd_ReadLogicZero(mgr); | ||
|  |   Cudd_Ref(tNode); | ||
|  |   while(i<array_n(expression)) | ||
|  |   { | ||
|  |     term=array_fetch(array_t * ,expression,i); | ||
|  |     tmp=retTerm(mgr,term,v); | ||
|  |     Cudd_Ref(tmp); | ||
|  |     tmp1=Cudd_bddOr(mgr,tNode,tmp); | ||
|  |     Cudd_Ref(tmp1); | ||
|  |     Cudd_RecursiveDeref(mgr,tNode); | ||
|  |     tNode=tmp1; | ||
|  |     i++;     | ||
|  |   }  | ||
|  |   return tNode; | ||
|  | } | ||
|  | 
 | ||
|  | DdNode * retTerm(DdManager * mgr,array_t *term, array_t * v) | ||
|  | /* given a term V1=v1 and V2=v2 ... Vn=vn, returns the BDD that implements that function */   | ||
|  | { | ||
|  |   factor f; | ||
|  |   DdNode * fNode, * tmp, *tmp1; | ||
|  |   int i; | ||
|  |    | ||
|  |   i=0; | ||
|  |   fNode=Cudd_ReadOne(mgr); | ||
|  |   Cudd_Ref(fNode); | ||
|  |   while (i<array_n(term)) | ||
|  |   { | ||
|  |     f=array_fetch(factor, term, i); | ||
|  |     tmp=retFactor(mgr,f,v); | ||
|  |     Cudd_Ref(tmp); | ||
|  |     tmp1= Cudd_bddAnd(mgr,fNode,tmp); | ||
|  |     Cudd_Ref(tmp1); | ||
|  |     Cudd_RecursiveDeref(mgr,fNode); | ||
|  |     fNode=tmp1; | ||
|  |     i++; | ||
|  |   }  | ||
|  |   return fNode; | ||
|  | } | ||
|  | 
 | ||
|  | DdNode * retFactor(DdManager * mgr, factor f, array_t * vars) | ||
|  | /* given a factor V=v, returns the BDD that implements that function */   | ||
|  | { | ||
|  |   int varIndex; | ||
|  |   int value; | ||
|  |   int i; | ||
|  |   int bit; | ||
|  |   variable v; | ||
|  |   DdNode * node, *booleanVar, * tmp; | ||
|  |   array_t * booleanVars; | ||
|  |    | ||
|  |    | ||
|  |   varIndex=f.var; | ||
|  |   value=f.value; | ||
|  |   v=array_fetch(variable, vars, varIndex); | ||
|  |   booleanVars=v.booleanVars; | ||
|  |   i=v.nBit-1; | ||
|  |   node=Cudd_ReadOne(mgr); | ||
|  |   Cudd_Ref(node); | ||
|  |   /* booelan var with index 0 in v.booleanVars is the most significant */ | ||
|  |   do { | ||
|  |     booleanVar=array_fetch(DdNode *,booleanVars,i); | ||
|  |     bit=value & 01; | ||
|  |     if (bit) | ||
|  |     { | ||
|  |       tmp=Cudd_bddAnd(mgr,node,booleanVar); | ||
|  |       Cudd_Ref(tmp); | ||
|  |     } | ||
|  |     else | ||
|  |       { | ||
|  |       tmp=Cudd_bddAnd(mgr,node,Cudd_Not(booleanVar)); | ||
|  |       Cudd_Ref(tmp); | ||
|  |       } | ||
|  |     value=value>>1; | ||
|  |     i--; | ||
|  |     Cudd_RecursiveDeref(mgr,node); | ||
|  |     node=tmp; | ||
|  |   } while (i>=0); | ||
|  |   return node; | ||
|  | 
 | ||
|  | } | ||
|  | 
 | ||
|  | 
 | ||
|  | 
 | ||
|  | double Prob(DdNode *node, array_t * vars,array_t * bVar2mVar, GHashTable * nodes) | ||
|  | /* compute the probability of the expression rooted at node
 | ||
|  | nodes is used to store nodes for which the probability has alread been computed | ||
|  | so that it is not recomputed | ||
|  |  */ | ||
|  | { | ||
|  |   int index,mVarIndex,nBit; | ||
|  |   variable v; | ||
|  |   double res; | ||
|  |   double value; | ||
|  |   double * value_p; | ||
|  |   DdNode **key; | ||
|  |   double *rp; | ||
|  | 
 | ||
|  |   index=node->index; | ||
|  |   if (Cudd_IsConstant(node)) | ||
|  |   { | ||
|  |     value=node->type.value; | ||
|  |     return value; | ||
|  |   } | ||
|  |   else | ||
|  | { | ||
|  | 	 | ||
|  | 	value_p=g_hash_table_lookup(nodes,&node); | ||
|  | 	if (value_p!=NULL) | ||
|  | 	{ | ||
|  | 		return *value_p; | ||
|  | 	} | ||
|  | 	else | ||
|  |   	{ | ||
|  |     		mVarIndex=array_fetch(int,bVar2mVar,index); | ||
|  |     		v=array_fetch(variable,vars,mVarIndex); | ||
|  |     		nBit=v.nBit; | ||
|  |     		res=ProbBool(node,0,nBit,0,v,vars,bVar2mVar,nodes); | ||
|  | 		key=(DdNode **)malloc(sizeof(DdNode *)); | ||
|  | 		*key=node; | ||
|  | 		rp=(double *)malloc(sizeof(double)); | ||
|  | 		*rp=res; | ||
|  | 		g_hash_table_insert(nodes, key, rp); | ||
|  |     		return res; | ||
|  |   	} | ||
|  | } | ||
|  | } | ||
|  | 
 | ||
|  | double ProbBool(DdNode *node, int bits, int nBit,int posBVar,variable v, | ||
|  | array_t * vars,array_t * bVar2mVar, GHashTable * nodes) | ||
|  | /* explores a group of binary variables making up the multivalued variable v */ | ||
|  | { | ||
|  |   DdNode *T,*F; | ||
|  |   double p,res; | ||
|  |   array_t * probs; | ||
|  |    | ||
|  |   probs=v.probabilities; | ||
|  |   if (nBit==0) | ||
|  |   { | ||
|  |     if (bits>=array_n(probs)) | ||
|  |       return 0; | ||
|  |     else | ||
|  |     { | ||
|  |       p=array_fetch(double,probs,bits); | ||
|  |       res=p*Prob(node,vars,bVar2mVar,nodes); | ||
|  |       return res; | ||
|  |     } | ||
|  |   } | ||
|  |   else | ||
|  |   { | ||
|  |     if (correctPosition(node->index,v,node,posBVar)) | ||
|  |     { | ||
|  |       T = node->type.kids.T; | ||
|  |       F = node->type.kids.E; | ||
|  |       bits=bits<<1; | ||
|  |        | ||
|  |       res=ProbBool(T,bits+1,nBit-1,posBVar+1,v,vars,bVar2mVar,nodes)+  | ||
|  |         ProbBool(F,bits,nBit-1,posBVar+1,v,vars,bVar2mVar,nodes); | ||
|  |       return res; | ||
|  |     } | ||
|  |     else | ||
|  |     { | ||
|  |        | ||
|  |       bits=bits<<1; | ||
|  |       res=ProbBool(node,bits+1,nBit-1,posBVar+1,v,vars,bVar2mVar,nodes)+  | ||
|  |         ProbBool(node,bits,nBit-1,posBVar+1,v,vars,bVar2mVar,nodes); | ||
|  |       return res; | ||
|  |     } | ||
|  |   } | ||
|  | } | ||
|  | 
 | ||
|  | int correctPosition(int index,variable v, DdNode * node,int posBVar) | ||
|  | /* returns 1 is the boolean variable with index posBVar is in the correct position 
 | ||
|  | currently explored by ProbBool */ | ||
|  | { | ||
|  |   DdNode * bvar; | ||
|  |    | ||
|  |   bvar=array_fetch(DdNode *,v.booleanVars,posBVar); | ||
|  |   return bvar->index==index; | ||
|  | } |