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);
|
||
|
}
|