257 lines
		
	
	
		
			6.4 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			257 lines
		
	
	
		
			6.4 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 functions for interfacing Yap and C
 | |
| 	The arguments of the predicate compute_prob are parsed and translated into C data 
 | |
| 	structures
 | |
| */
 | |
| 
 | |
| #include "cplint.h"
 | |
| #include <math.h>
 | |
| #include <stdlib.h>
 | |
| #include <string.h>
 | |
| 
 | |
| 
 | |
| unsigned long dividend;
 | |
| 
 | |
| FILE *open_file (char *filename, const char *mode);
 | |
| void reverse(char s[]);
 | |
| static int compute_prob(void);
 | |
| 
 | |
| void createVars(array_t * vars, YAP_Term t,DdManager * mgr, array_t * bVar2mVar,int create_dot,  char inames[1000][20])
 | |
| /* adds the boolean variables to the BDD and returns
 | |
| an array_t containing them (array_t is defined in the util library of glu)
 | |
| returns also the names of the variables to be used to save the ADD in dot format
 | |
|  */
 | |
| {
 | |
|      	YAP_Term  varTerm,probTerm;
 | |
| 	int varIndex,nVal,i,b;
 | |
| 	variable v;	
 | |
| 	char numberVar[10],numberBit[10];
 | |
| 	double p;
 | |
| 	b=0;
 | |
| 
 | |
| 	while(YAP_IsPairTerm(t))
 | |
| 	{
 | |
| 		varTerm=YAP_HeadOfTerm(t);
 | |
| 		varIndex=YAP_IntOfTerm(YAP_HeadOfTerm(varTerm));
 | |
| 
 | |
|       		varTerm=YAP_TailOfTerm(varTerm);
 | |
| 		nVal=YAP_IntOfTerm(YAP_HeadOfTerm(varTerm));
 | |
| 		varTerm=YAP_TailOfTerm(varTerm);
 | |
|       		probTerm=YAP_HeadOfTerm(varTerm);
 | |
| 		v.nVal=nVal;
 | |
| 		v.nBit=(int)ceil(log(nVal)/log(2));
 | |
| 		v.probabilities=array_alloc(double,0);
 | |
| 		v.booleanVars=array_alloc(DdNode *,0);
 | |
| 		for (i=0;i<nVal;i++)
 | |
| 		{
 | |
| 			if (create_dot)
 | |
| 			{
 | |
| 				strcpy(inames[b+i],"X");
 | |
| 				sprintf(numberVar,"%d",varIndex);
 | |
| 				strcat(inames[b+i],numberVar);
 | |
| 				strcat(inames[b+i],"_");
 | |
| 				sprintf(numberBit,"%d",i);
 | |
| 				strcat(inames[b+i],numberBit);
 | |
| 			}
 | |
| 			p=YAP_FloatOfTerm(YAP_HeadOfTerm(probTerm));
 | |
| 			array_insert(double,v.probabilities,i,p);
 | |
| 			probTerm=YAP_TailOfTerm(probTerm);
 | |
| 			array_insert(DdNode *,v.booleanVars,i,Cudd_bddIthVar(mgr,b+i));
 | |
| 			array_insert(int,bVar2mVar,b+i,varIndex);
 | |
| 		}
 | |
| 		Cudd_MakeTreeNode(mgr,b,nVal,MTR_FIXED);
 | |
| 		b=b+nVal;
 | |
| 		array_insert(variable,vars,varIndex,v);
 | |
| 		t=YAP_TailOfTerm(t);
 | |
| 	}
 | |
| }
 | |
| 
 | |
| void createExpression(array_t * expression, YAP_Term t)
 | |
| /* returns the expression as an array_t of terms (cubes) starting from the prolog lists of terms
 | |
| each term is an array_t of factors obtained from a prolog list of factors
 | |
| each factor is a couple (index of variable, index of value) obtained from a prolog list containing 
 | |
| two integers
 | |
| */
 | |
| {
 | |
|      	YAP_Term  termTerm,factorTerm;
 | |
| 	factor f;	
 | |
| 	int i,j;
 | |
| 	array_t * term;
 | |
| 
 | |
| 	i=0;
 | |
| 	while(YAP_IsPairTerm(t))
 | |
| 	{
 | |
| 		term=array_alloc(factor,0);
 | |
| 		termTerm=YAP_HeadOfTerm(t);
 | |
| 		j=0;
 | |
| 		while(YAP_IsPairTerm(termTerm))
 | |
| 		{
 | |
| 			factorTerm=YAP_HeadOfTerm(termTerm);
 | |
| 			f.var=YAP_IntOfTerm(YAP_HeadOfTerm(factorTerm));
 | |
| 			f.value=YAP_IntOfTerm(YAP_HeadOfTerm(YAP_TailOfTerm(factorTerm)));
 | |
| 			array_insert(factor,term,j,f);
 | |
| 			termTerm=YAP_TailOfTerm(termTerm);
 | |
| 			j++;
 | |
| 		}
 | |
| 		array_insert(array_t *,expression,i,term);
 | |
| 		t=YAP_TailOfTerm(t);
 | |
| 		i++;
 | |
| 	}
 | |
| }
 | |
| 
 | |
| static int compute_prob(void)
 | |
| /* this is the function that implements the compute_prob predicate used in pp.pl
 | |
| */
 | |
| {
 | |
| 	YAP_Term out,arg1,arg2,arg3,arg4;
 | |
| 	array_t * variables,* expression, * bVar2mVar;
 | |
| 	DdNode * function, * add;
 | |
| 	DdManager * mgr;
 | |
| 	int nBVar,i,j,intBits,create_dot;
 | |
|         FILE * file;
 | |
|         DdNode * array[1];
 | |
|         char * onames[1];
 | |
|         char inames[1000][20];
 | |
| 	char * names[1000];
 | |
| 	GHashTable  * nodes; /* hash table that associates nodes with their probability if already 
 | |
| 				computed, it is defined in glib */
 | |
| 	Cudd_ReorderingType order;
 | |
| 	arg1=YAP_ARG1;
 | |
| 	arg2=YAP_ARG2;
 | |
| 	arg3=YAP_ARG3;
 | |
| 	arg4=YAP_ARG4;
 | |
| 
 | |
|   	mgr=Cudd_Init(0,0,CUDD_UNIQUE_SLOTS,CUDD_CACHE_SLOTS,0);
 | |
| 	variables=array_alloc(variable,0);
 | |
| 	bVar2mVar=array_alloc(int,0);
 | |
| 	create_dot=YAP_IntOfTerm(arg4);
 | |
| 	createVars(variables,arg1,mgr,bVar2mVar,create_dot,inames);
 | |
|         //Cudd_PrintInfo(mgr,stderr);
 | |
| 
 | |
| 	/* automatic variable reordering, default method CUDD_REORDER_SIFT used */
 | |
| 	//printf("status %d\n",Cudd_ReorderingStatus(mgr,&order));
 | |
| 	//printf("order %d\n",order);
 | |
| 
 | |
| 	Cudd_AutodynEnable(mgr,CUDD_REORDER_SAME); 
 | |
| /*	 Cudd_AutodynEnable(mgr, CUDD_REORDER_RANDOM_PIVOT);
 | |
| 	printf("status %d\n",Cudd_ReorderingStatus(mgr,&order));
 | |
|         printf("order %d\n",order);
 | |
| 	printf("%d",CUDD_REORDER_RANDOM_PIVOT);
 | |
| */
 | |
| 
 | |
| 
 | |
| 	expression=array_alloc(array_t *,0);
 | |
| 	createExpression(expression,arg2);	
 | |
| 
 | |
| 	function=retFunction(mgr,expression,variables);
 | |
| 	/* the BDD build by retFunction is converted to an ADD (algebraic decision diagram)
 | |
| 	because it is easier to interpret and to print */
 | |
| 	add=Cudd_BddToAdd(mgr,function);
 | |
| 	//Cudd_PrintInfo(mgr,stderr);
 | |
| 
 | |
| 	if (create_dot)
 | |
| 	/* if specified by the user, a dot file for the BDD is written to cpl.dot */
 | |
| 	{	
 | |
| 		nBVar=array_n(bVar2mVar);
 | |
| 		for(i=0;i<nBVar;i++)
 | |
| 		   names[i]=inames[i];
 | |
| 	  	array[0]=add;
 | |
| 		onames[0]="Out";
 | |
| 		file = open_file("cpl.dot", "w");
 | |
| 		Cudd_DumpDot(mgr,1,array,names,onames,file);
 | |
|   		fclose(file);
 | |
| 	}
 | |
| 	
 | |
| 	nodes=g_hash_table_new(my_hash,my_equal);
 | |
| 	intBits=sizeof(unsigned int)*8;
 | |
| 	/* dividend is a global variable used by my_hash 
 | |
| 	   it is equal to an unsigned int with binary representation 11..1 */ 
 | |
| 	dividend=1;
 | |
| 	for(j=1;j<intBits;j++)
 | |
| 	{
 | |
| 		dividend=(dividend<<1)+1;
 | |
| 	}
 | |
| 	out=YAP_MkFloatTerm(Prob(add,variables,bVar2mVar,nodes));
 | |
| 	g_hash_table_foreach (nodes,dealloc,NULL);
 | |
| 	g_hash_table_destroy(nodes);
 | |
| 	Cudd_Quit(mgr);
 | |
| 	array_free(variables);
 | |
|  	array_free(bVar2mVar);
 | |
| 	array_free(expression);
 | |
|     	return(YAP_Unify(out,arg3));
 | |
| }
 | |
| /*
 | |
| int compare(char *a, char *b)
 | |
| {
 | |
| 	int aval,bval;
 | |
| 	aval=(int) *((DdNode **)a);
 | |
| 	aval=(int) *((DdNode **)b);
 | |
| 
 | |
| 	if (aval<bval)
 | |
| 		return -1;
 | |
| 	else
 | |
|  		if (aval>bval)
 | |
| 			return 1;
 | |
| 		else
 | |
| 			return 0;
 | |
| }
 | |
| */
 | |
| void init_my_predicates()
 | |
| /* function required by YAP for intitializing the predicates defined by a C function*/
 | |
| {
 | |
|      YAP_UserCPredicate("compute_prob",compute_prob,4);
 | |
| }
 | |
|  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;
 | |
| 
 | |
| }
 | |
| void reverse(char s[])
 | |
| /* reverses a string */
 | |
| {
 | |
| 	int i,c,j;
 | |
| 	for (i=0,j=strlen(s)-1;i<j;i++,j--)
 | |
| 	{
 | |
| 		c=s[i];
 | |
| 		s[i]=s[j];
 | |
| 		s[j]=c;
 | |
| 	}
 | |
| }
 | |
| 
 | |
| gint my_equal(gconstpointer v,gconstpointer v2)
 | |
| /* function used by GHashTable to compare two keys */
 | |
| {
 | |
| 	DdNode *a,*b;
 | |
| 	a=*(DdNode **)v;
 | |
| 	b=*(DdNode **)v2;
 | |
| 	return (a==b);
 | |
| }
 | |
| guint my_hash(gconstpointer key)
 | |
| /* function used by GHashTable to hash a key */
 | |
| {
 | |
| 	unsigned int h;
 | |
| 	h=(unsigned int)((unsigned long) *((DdNode **)key) % dividend);
 | |
| 	return h;
 | |
| }
 | |
| void  dealloc(gpointer key,gpointer value,gpointer user_data)
 | |
| {
 | |
| 	free(key);
 | |
| 	free(value);
 | |
| }
 |