/* 2012 (C) Jussi Rintanen jrintanen.jr@gmail.com */ #include #include #include #include #include "asyntax.h" #include "tables.h" #include "intsets.h" #include "ordintsets.h" #include "operators.h" #include "main.h" //#include "instantiation.h" #define noDEBUG /*****************************************************************************/ /*************************** Preprocess **************************************/ /*****************************************************************************/ int binding[200]; int nOfBindings; int scope[200]; #ifdef CFMA #include "Cground.c" #endif /* replace parameter variables by their index in the parameter list */ int NEWparamindex(int i,int qdepth) { int j; for(j=qdepth-1;j>=0;j--) { if(scope[j] == i) return -1-j; } fprintf(stderr,"ERROR: variable %s is not a parameter\n",symbol(i)); exit(1); } /* This applies paramindex in the right places */ void NEWpreprocessatom(atom a,int qdepth) { int i; for(i=2;i<2+a[1];i++) { if(isvar(a[i])) { a[i] = NEWparamindex(a[i],qdepth); } } } /* This applies paramindex in the right places. */ /* For quantification, this replaces the quantified variables name with the next available integer index. */ void NEWpreprocessfma(Sfma *f,int qdepth) { Sfmalist *l; switch(Sfmatypeof(f)) { case STRUE: case SFALSE: break; case Spatom: case Snatom: NEWpreprocessatom(f->a,qdepth); break; case Sdisj: case Sconj: #ifdef CFMA f->cnt = listlen(f->juncts); #endif l = f->juncts; while(l != NULL) { NEWpreprocessfma(l->hd,qdepth); l = l->tl; } break; case Sforall: case Sforsome: if(f->ss->tl) { /* Split multiple quantification. */ Sfma *f1 = (Sfma*)malloc(sizeof(Sfma)); f1->t = f->t; f1->ss = f->ss->tl; f1->f = f->f; f->ss->tl = NULL; f->f = f1; } scope[qdepth] = f->ss->v; #ifdef DEBUG printf("scope[%i] = %s\n",qdepth,symbol(f->ss->v)); #endif f->ss->v = -1-qdepth; NEWpreprocessfma(f->f,qdepth+1); break; case Seq: case Sneq: if(isvar(f->p1)) f->p1 = NEWparamindex(f->p1,qdepth); if(isvar(f->p2)) f->p2 = NEWparamindex(f->p2,qdepth); break; } } /* This applies paramindex in the right places */ void NEWpreprocesseff(Seff *e,int qdepth) { Sfmalist *l; switch(e->t) { case SEpatom: case SEnatom: NEWpreprocessatom(e->a,qdepth); break; case SEconj: l = e->juncts; while(l != NULL) { NEWpreprocesseff(l->hd,qdepth); l = l->tl; } break; case SEforall: if(e->ss->tl) { /* Split multiple quantification. */ Seff *e1 = (Seff*)malloc(sizeof(Seff)); e1->t = SEforall; e1->ss = e->ss->tl; e1->effect = e->effect; e->ss->tl = NULL; e->effect = e1; } scope[qdepth] = e->ss->v; #ifdef DEBUG printf("scope[%i] = %s\n",qdepth,symbol(e->ss->v)); #endif e->ss->v = -1-qdepth; NEWpreprocesseff(e->effect,qdepth+1); break; case SEwhen: NEWpreprocessfma(e->cond,qdepth); NEWpreprocesseff(e->effect,qdepth); break; } } void NEWpreprocessoperators() { int i,qdepth; typedvarlist *ps; for(i=0;iv)); #endif scope[qdepth++] = ps->v; ps = ps->tl; } // printf("Qdepth = %i\n",qdepth); NEWpreprocessfma(Sactions[i].precon,qdepth); NEWpreprocesseff(Sactions[i].effect,qdepth); #ifdef DEBUG printf("AFTER:\n"); #endif if(flagShowInput) printSaction(&Sactions[i]); } NEWpreprocessfma(Sgoal,0); } /***************************************************************************/ /********************************* Grounding *******************************/ /***************************************************************************/ Sfma *whenstack[1000]; /* Array for nested when-conditions */ int NEWnOfEffectLitsL(Sefflist *); int NEWnOfEffectLits(Seff *se) { switch(se->t) { case SEpatom: return 1; case SEnatom: return 1; case SEconj: return NEWnOfEffectLitsL(se->juncts); case SEwhen: return 0; case SEforall: return (getdomainsize(se->ss->t)) * NEWnOfEffectLits(se->effect); } return 0; } int NEWnOfEffectLitsL(Sefflist *l) { if(l == NULL) return 0; return NEWnOfEffectLits(l->hd) + NEWnOfEffectLitsL(l->tl); } int *NEWinserteffectlitsL(int *,Sefflist *,int *); int *NEWinserteffectlits(int *a,Seff *se,int *b) { int *vals; switch(se->t) { case SEpatom: *a = fePLIT(atomindex(se->a,b)); return a+1; case SEnatom: *a = feNLIT(atomindex(se->a,b)); return a+1; case SEconj: return NEWinserteffectlitsL(a,se->juncts,b); case SEwhen: return a; case SEforall: vals = getdomain(se->ss->t); while(*vals != -1) { b[-1-se->ss->v] = *vals; a = NEWinserteffectlits(a,se->effect,b); vals = vals + 1; } return a; default: return a; } } int *NEWinserteffectlitsL(int *a,Sefflist *l,int *b) { if(l == NULL) return a; return NEWinserteffectlitsL(NEWinserteffectlits(a,l->hd,b),l->tl,b); } int someunconditional(Seff *se) { Sefflist *ses; switch(se->t) { case SEconj: ses = se->juncts; while(ses != NULL) { if(someunconditional(ses->hd)) return 1; ses = ses->tl; } return 0; case SEpatom: return 1; case SEnatom: return 1; case SEwhen: return 0; case SEforall: return someunconditional(se->effect); default: return 0; } } fma *NEWgroundfma(Sfma *,int *); eff *NEWlocateconditionals(Seff *se,int *b,eff *ac,int whennesting) { int *vals,i,*ptr; eff *e,*ac0; Sefflist *ses; switch(se->t) { case SEconj: ses = se->juncts; while(ses != NULL) { ac = NEWlocateconditionals(ses->hd,b,ac,whennesting); ses = ses->tl; } return ac; case SEwhen: e = (eff *)malloc(sizeof(eff)); whenstack[whennesting] = se->cond; ac0 = NEWlocateconditionals(se->effect,b,ac,whennesting+1); if(se->cond->t == SFALSE) return ac0; if(!someunconditional(se->effect)) return ac0; if(whennesting == 0) { /* Non-nested when */ e->condition = NEWgroundfma(se->cond,b); #ifdef CFMA e->ccondition = Cgroundfma(se->cond,b); // printcfma(e->ccondition); #endif } else{ /* Nesting of 2 or more whens */ fmalist *fs = NULL; for(i=0;i<=whennesting;i++) { fs = fmacons(NEWgroundfma(whenstack[i],b),fs); } e->condition = (fma *)malloc(sizeof(fma)); e->condition->t = conj; e->condition->juncts = fs; } e->effectlits = (int *)malloc((NEWnOfEffectLits(se->effect)+1) * sizeof(int)); ptr = NEWinserteffectlits(e->effectlits,se->effect,b); *ptr = -1; e->tl = ac0; return e; case SEforall: vals = getdomain(se->ss->t); while(*vals != -1) { b[-1-se->ss->v] = *vals; ac = NEWlocateconditionals(se->effect,b,ac,whennesting); vals = vals + 1; } return ac; default: return ac; } } void NEWgroundeff(Seff *se,int *b, eff *e) { int *ptr,cnt; // eff *e = (eff *)malloc(sizeof(eff)); e->condition = (fma *)malloc(sizeof(fma)); e->condition->t = TRUE; #ifdef CFMA e->ccondition = cTRUE; #endif cnt = NEWnOfEffectLits(se); // printf("There are %i effect literals: ",cnt); e->effectlits = (int *)malloc((cnt+1) * sizeof(int)); ptr = NEWinserteffectlits(e->effectlits,se,b); *ptr = -1; // printlitarr(e->effectlits); e->tl = NEWlocateconditionals(se,b,NULL,0); } fmalist *NEWgroundfmalist(Sfmalist *,int *); fma *NEWgroundfma(Sfma *sf,int *b) { int *vals; fma *f = (fma *)malloc(sizeof(fma)); switch(Sfmatypeof(sf)) { case STRUE: f->t = TRUE; break; case SFALSE: f->t = FALSE; break; case Sconj: f->t = conj; f->juncts = NEWgroundfmalist(sf->juncts,b); break; case Sdisj: f->t = disj; f->juncts = NEWgroundfmalist(sf->juncts,b); break; case Seq: if(bvalue(sf->p1,b) == bvalue(sf->p2,b)) { f->t = TRUE; } else { f->t = FALSE; } break; case Sneq: if(bvalue(sf->p1,b) == bvalue(sf->p2,b)) { f->t = FALSE; } else { f->t = TRUE; } break; case Spatom: f->t = patom; f->a = atomindex(sf->a,b); break; case Snatom: f->t = natom; f->a = atomindex(sf->a,b); break; case Sforall: /* Iterate over all values of the variable. */ f->t = conj; f->juncts = NULL; vals = getdomain(sf->ss->t); while(*vals != -1) { b[-1-sf->ss->v] = *vals; f->juncts = fmacons(NEWgroundfma(sf->f,b),f->juncts); vals = vals + 1; } break; case Sforsome: /* Iterate over all values of the variable. */ f->t = disj; f->juncts = NULL; vals = getdomain(sf->ss->t); while(*vals != -1) { b[-1-sf->ss->v] = *vals; f->juncts = fmacons(NEWgroundfma(sf->f,b),f->juncts); vals = vals + 1; } break; } return f; } fmalist *NEWgroundfmalist(Sfmalist *l,int *b) { if(l == NULL) return NULL; return fmacons(NEWgroundfma(l->hd,b),NEWgroundfmalist(l->tl,b)); } /* Is it a variable, and not assigned? */ inline int assignedvar(int v,int i) { if(v < 0 && (-1-v) <= i) return 1; else return 0; } /* Check all static atomic conjuncts of precon to found out whether the bindings until parameter i are compatible with the initial state. */ inline int staticp(int i) { return index2stentry[i]->staticpredicate; } /* Generate bindings so that the formula f is not trivially violated by the true literals in the initial state in the sense that there is a positive literal as a conjunct of f that is false in the initial state. How is this done? */ /* Test whether the formula f with the current partial binding is compatible with the true literals in the initial state. This is only tested for positive literals appearing as conjuncts of the formula. All such literals must match the initial state. */ int legalstaticbindingA(int i,int *a) { int j; atom *as; /* Go through the atoms in the initial state description, and check. */ as = Sinit; if(staticp(a[0]) == 0) return 1; while(*as != NULL) { /* Go through all initial state atoms. */ #ifdef DEBUG printf("Matching "); printSfma(f); printf(" against "); printatom(*as); printf(" with"); for(j=0;j<=i;j++) { printf(" #%i:%s",j,symbol(binding[j])); } printf("\n"); #endif if((*as)[0] == a[0]) { /* Same predicate. Binding OK? */ for(j=2;jt) { case Spatom: return legalstaticbindingA(i,f->a); case Sconj: fs = f->juncts; while(fs != NULL) { if(legalstaticbinding(i,fs->hd) == 0) return 0; fs = fs->tl; } default: return 1; } return 1; } #define noNEWSTATICB #ifdef NEWSTATICB int litcnt; int *trueposlits[1000]; int relevantbindings[100000]; /* General procedure for identifying relevant bindings. Check every conjunct of the precondition and every true variable in the initial state, and check if there is a match, binding the current parameter. Match the first literal first, to identify a candidate value. If there is a second (and further literals), check whether the match is good. */ void identifyposlits(int i,Sfma *f) { Sfmalist *fs; int j; switch(f->t) { case Spatom: if(!staticp(f->a[0])) return; for(j=0;ja[1];j++) { if(f->a[j+2] == -1-i) { trueposlits[litcnt++] = f->a; printatom(f->a); return; } } return; case Sconj: fs = f->juncts; while(fs != NULL) { identifyposlits(i,fs->hd); fs = fs->tl; } return; default: return; } } int match(int *patom,int *initlit,int param,int *value) { int i; *value = -1; if(initlit[0] != patom[0]) return 0; /* Wrong predicate */ if(initlit[1] != patom[1]) return 0; /* Wrong arity */ for(i=0;i 0); printf("\n"); /* Match first lit with the initial state to obtain a binding, and verify that others match with this binding. */ printf("Relevant bindings for parameter %i are...\n",i); as = Sinit; while(*as != NULL) { printf("Trying match with "); printatom(*as); printf(":"); if(match(trueposlits[0],*as,i,&value)) { /* There is a match. */ for(j=0;jhd)); #ifdef DEBUG printf("----------------------------------\n"); #endif #ifdef NEWSTATICB NEWgothrough(i+1,sc,domains,staticrestriction); #else if(legalstaticbinding(i,Sactions[sc].precon)) { /* Legal binding? */ NEWgothrough(i+1,sc,domains,staticrestriction); } #endif l = l + 1; } } else { /* Value not restricted by a static predicate. */ while(*l != -1) { binding[i] = *l; // printf("(%s)",symbol(l->hd)); NEWgothrough(i+1,sc,domains,staticrestriction); l = l + 1; } } } else { #ifdef DEBUG printf("INSTANTIATE\n"); #endif nOfActions += 1; if(nOfActions >= maxActions) { maxActions = 2*maxActions; actions = (action *)realloc(actions,maxActions * sizeof(action)); } actions[nOfActions-1].name = (int *)malloc((nOfBindings+2) * sizeof(int)); actions[nOfActions-1].name[0] = Sactions[sc].name; copybindings(actions[nOfActions-1].name+1,binding,nOfBindings); actions[nOfActions-1].precon = NEWgroundfma(Sactions[sc].precon,binding); #ifdef CFMA actions[nOfActions-1].cprecon = Cgroundfma(Sactions[sc].precon,binding); // printcfma(actions[nOfActions-1].cprecon); #endif NEWgroundeff(Sactions[sc].effect,binding,&(actions[nOfActions-1].effects)); actions[nOfActions-1].cost = Sactions[sc].cost; // printaction(nOfActions-1); } } /* Does parameter i occur in a static positive literal, a conjunct of f? */ int occursinstatic(int i,Sfma *f) { Sfmalist *fs; int j; switch(f->t) { case Spatom: if(!staticp(f->a[0])) return 0; for(j=0;ja[1];j++) { if(f->a[j+2] == -1-i) { return 1; } } return 0; case Sconj: fs = f->juncts; while(fs != NULL) { if(occursinstatic(i,fs->hd)) return 1; fs = fs->tl; } return 0; default: return 0; } } void NEWgroundoperators() { int i,j; int *domains[1000]; int binding[1000]; int staticrestriction[1000]; atom *al; NEWpreprocessoperators(); initactions(); /* initialize the ground action data structure */ initatomtable(); /* initialize the tables for atoms */ for(i=0;iv)); #endif domains[nOfBindings] = getdomain(l->t); nOfBindings += 1; l = l->tl; } #ifdef ASSERTS assert(nOfBindings < 100); #endif /* Go through all parameter assignments and ground */ NEWgothrough(0,i,domains,staticrestriction); } goal = NEWgroundfma(Sgoal,binding); /* Go through the initial state description to assign indices to initial state atoms. */ al = Sinit; while(*al != NULL) { atomindex(*al,NULL); al = al + 1; } initialstate = (int *)malloc(sizeof(int) * nOfAtoms); for(i=0;i=0); assert(j