606 lines
12 KiB
C
606 lines
12 KiB
C
|
|
/* 2012 (C) Jussi Rintanen jrintanen.jr@gmail.com */
|
|
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
|
|
#include "asyntax.h"
|
|
#include "intsets.h"
|
|
#include "ordintsets.h"
|
|
#include "operators.h"
|
|
#include "tables.h"
|
|
#include "invariants.h"
|
|
#include "main.h"
|
|
|
|
#define noDEBUG
|
|
|
|
|
|
/* Local copies (for inlining) of intsets.c functions */
|
|
|
|
int *iITptr;
|
|
int iITcounter;
|
|
|
|
inline void iITstart(intset s) {
|
|
iITcounter = s->nOfEls;
|
|
iITptr = s->elements;
|
|
}
|
|
|
|
inline int iITnext(int *i) {
|
|
if(iITcounter <= 0) return 0;
|
|
iITcounter -= 1;
|
|
*i = *(iITptr++);
|
|
return 1;
|
|
}
|
|
|
|
/* */
|
|
|
|
void printlitlist(intset s) {
|
|
int i;
|
|
iITstart(s);
|
|
while(iITnext(&i)) {
|
|
if(i&1) printf(" -");
|
|
else printf(" ");
|
|
printatomi(feVAR(i));
|
|
}
|
|
}
|
|
|
|
void showInvariants() {
|
|
int i,cntpersistent;
|
|
|
|
cntpersistent = 0;
|
|
printf("PERSISTENT LITERALS:"); fflush(stdout);
|
|
for(i=0;i<nOfAtoms;i++) {
|
|
if(onelits[i] == 1) { printf(" "); printatomi(i); }
|
|
else if(onelits[i] == 0) { printf(" -"); printatomi(i); }
|
|
if(onelits[i] != -1) cntpersistent += 1;
|
|
}
|
|
printf("\nThere are %i persistent literals (out of total of %i literals).\n",cntpersistent,nOfAtoms);
|
|
|
|
printf("Invariants:\n");
|
|
|
|
for(i=0;i<nOfAtoms;i++) {
|
|
printatomi(i); printf(" OR:");
|
|
printlitlist(twolits[fePLIT(i)]);
|
|
printf("\n");
|
|
|
|
printf("-"); printatomi(i); printf(" OR:");
|
|
printlitlist(twolits[feNLIT(i)]);
|
|
printf("\n");
|
|
}
|
|
}
|
|
|
|
void showInvariantsBrief() {
|
|
int i;
|
|
printf("True literals:");
|
|
for(i=0;i<nOfAtoms;i++) {
|
|
if(onelits[i] == 1) { printf(" "); printatomi(i); }
|
|
else if(onelits[i] == 0) { printf(" -"); printatomi(i); }
|
|
}
|
|
printf("\nTrue 2-literal clauses:\n");
|
|
|
|
for(i=0;i<nOfAtoms;i++) {
|
|
|
|
printatomi(i); printf(" OR ");
|
|
printlitlist(twolits[fePLIT(i)]);
|
|
printf("\n");
|
|
|
|
printf("-"); printatomi(i); printf(" OR ");
|
|
printlitlist(twolits[feNLIT(i)]);
|
|
printf("\n");
|
|
}
|
|
}
|
|
|
|
|
|
|
|
//#define iITnext ITnext
|
|
//#define iITstart ITstart
|
|
|
|
int *onelits;
|
|
intset *twolits;
|
|
|
|
/* Preprocessing for operators:
|
|
For each operator and conditional effect compute
|
|
|
|
A. list of literals guaranteed to be true before
|
|
the conditional effect is executed
|
|
|
|
B. list of literals guaranteed to be true after
|
|
|
|
Literals derived from the precondition are included in lists A.
|
|
|
|
If there are unconditional effects (condition TRUE) then
|
|
these are included in all lists B.
|
|
|
|
Literals in list A that are guaranteed not to be falsified
|
|
by a simultaneous conditional effect are included in B.
|
|
|
|
*/
|
|
|
|
typedef struct _llist {
|
|
intset before;
|
|
intset after;
|
|
} llist;
|
|
|
|
/* Compute effect literals consisting of the positive, the negative
|
|
and the ones in a conditional effect with an always-true condition. */
|
|
|
|
void addeffectlitsL(int *lits,eff *current,eff *all,intset s) {
|
|
int *ptr;
|
|
while(*lits != -1) { ISinsert(*lits,s); lits = lits + 1; }
|
|
while(all != NULL) {
|
|
if(all->condition->t == TRUE && all != current) {
|
|
ptr = all->effectlits;
|
|
while(*ptr != -1) {
|
|
ISinsert(*ptr,s);
|
|
ptr = ptr+1;
|
|
}
|
|
}
|
|
all = all->tl;
|
|
}
|
|
}
|
|
|
|
void guaranteedtrue(fma *f,intset ac) {
|
|
fmalist *fs;
|
|
switch(f->t) {
|
|
case FALSE:
|
|
case TRUE:
|
|
break;
|
|
case conj:
|
|
fs = f->juncts;
|
|
while(fs != NULL) {
|
|
guaranteedtrue(fs->hd,ac);
|
|
fs = fs->tl;
|
|
}
|
|
break;
|
|
case disj: break;
|
|
case patom: ISinsert(fePLIT(f->a),ac); break;
|
|
case natom: ISinsert(feNLIT(f->a),ac); break;
|
|
}
|
|
}
|
|
|
|
int nofcondeffs(eff *e) {
|
|
int cnt;
|
|
cnt = 0;
|
|
while(e != NULL) {
|
|
cnt = cnt + 1;
|
|
e = e->tl;
|
|
}
|
|
return cnt;
|
|
}
|
|
|
|
llist **prepros; /* */
|
|
|
|
void preprocess() {
|
|
int i,j,effcnt;
|
|
intset preconlits;
|
|
eff *e;
|
|
|
|
prepros = (llist **)statmalloc(401,nOfActions * sizeof(llist *));
|
|
preconlits = IScreate(1000);
|
|
|
|
for(i=0;i<nOfActions;i++) {
|
|
|
|
e = &(actions[i].effects);
|
|
|
|
effcnt = nofcondeffs(e);
|
|
|
|
prepros[i] = statmalloc(402,sizeof(llist) * effcnt);
|
|
|
|
#ifdef DEBUG
|
|
printf("Preprocessing for operator %i:",i); fflush(stdout);
|
|
printaction(i); fflush(stdout);
|
|
#endif
|
|
|
|
ISmakeempty(preconlits);
|
|
|
|
guaranteedtrue(actions[i].precon,preconlits);
|
|
|
|
j = 0;
|
|
|
|
while(e != NULL) { /* Go through the conditional effects */
|
|
|
|
prepros[i][j].before = IScreateSize(10);
|
|
|
|
guaranteedtrue(e->condition,prepros[i][j].before);
|
|
ISaddelements(preconlits,prepros[i][j].before);
|
|
|
|
#ifdef DEBUG
|
|
printf("BEFORE"); fflush(stdout);
|
|
printlitlist(prepros[i][j].before); fflush(stdout);
|
|
printf("\n"); fflush(stdout);
|
|
#endif
|
|
|
|
prepros[i][j].after = IScreateSize(20);
|
|
|
|
addeffectlitsL(e->effectlits,e,&(actions[i].effects),prepros[i][j].after);
|
|
#ifdef DEBUG
|
|
printf("AFTER"); fflush(stdout);
|
|
printlitlist(prepros[i][j].after); fflush(stdout);
|
|
printf("\n\n"); fflush(stdout);
|
|
#endif
|
|
|
|
e = e->tl;
|
|
j = j + 1;
|
|
}
|
|
|
|
}
|
|
}
|
|
|
|
int **alleffectlits;
|
|
|
|
int nofeffectlits(eff *e) {
|
|
int cnt = 0;
|
|
int *ptr;
|
|
|
|
while(e != NULL) {
|
|
ptr = e->effectlits;
|
|
while(*ptr != -1) {
|
|
cnt = cnt + 1;
|
|
ptr = ptr + 1;
|
|
}
|
|
e = e-> tl;
|
|
}
|
|
return cnt;
|
|
}
|
|
|
|
void preprocess2() {
|
|
int i,sz;
|
|
eff *e;
|
|
int *ptr,*fill;
|
|
|
|
alleffectlits = (int **)statmalloc(499,nOfActions * sizeof(int *));
|
|
for(i=0;i<nOfActions;i++) {
|
|
sz = 1 + nofeffectlits(&(actions[i].effects));
|
|
alleffectlits[i] = (int *)statmalloc(498,sz * sizeof(int));
|
|
fill = alleffectlits[i];
|
|
e = &(actions[i].effects);
|
|
while(e != NULL) {
|
|
ptr = e->effectlits;
|
|
while(*ptr != -1) {
|
|
*fill = *ptr;
|
|
fill = fill + 1;
|
|
ptr = ptr + 1;
|
|
}
|
|
e = e->tl;
|
|
}
|
|
*fill = -1;
|
|
}
|
|
}
|
|
|
|
#ifdef CFMA
|
|
inline int ctruep(cfma f) {
|
|
|
|
switch(((int)f)&7) {
|
|
|
|
case cNATOMtag: return (onelits[((int)f) >> 3] != 1);
|
|
case cPATOMtag: return (onelits[((int)f) >> 3] != 0);
|
|
case cTRUEtag: return 1;
|
|
case cFALSEtag: return 0;
|
|
|
|
default:
|
|
|
|
if(((int)(*f))&1) { /* Conjunction */
|
|
|
|
int i,cnt;
|
|
cnt = ((int)(f[0])) >> 1;
|
|
|
|
for(i=0;i<cnt;i++) {
|
|
if(!ctruep(f[i+1])) return 0;
|
|
}
|
|
return 1;
|
|
|
|
} else { /* Disjunction */
|
|
|
|
int i,cnt;
|
|
cnt = ((int)(f[0])) >> 1;
|
|
|
|
for(i=0;i<cnt;i++) {
|
|
if(ctruep(f[i+1])) return 1;
|
|
}
|
|
return 0;
|
|
}
|
|
}
|
|
return 0;
|
|
}
|
|
#endif
|
|
|
|
int truep(fma *f) {
|
|
fmalist *fs;
|
|
switch(f->t) {
|
|
case natom: return (onelits[f->a] != 1);
|
|
case patom: return (onelits[f->a] != 0);
|
|
case disj:
|
|
fs = f->juncts;
|
|
while(fs != NULL) {
|
|
if(truep(fs->hd)) return 1;
|
|
fs = fs->tl;
|
|
}
|
|
return 0;
|
|
case conj:
|
|
fs = f->juncts;
|
|
while(fs != NULL) {
|
|
if(!truep(fs->hd)) return 0;
|
|
fs = fs->tl;
|
|
}
|
|
return 1;
|
|
case TRUE: return 1;
|
|
case FALSE: return 0;
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
//int notmadefalse(int l,eff *e) {
|
|
// int *ls;
|
|
// while(e != NULL) {
|
|
// ls = e->effectlits;
|
|
// while(*ls != -1) {
|
|
// if(l == feNEG(*ls)) return 0;
|
|
// ls = ls + 1;
|
|
// }
|
|
// e = e->tl;
|
|
// }
|
|
// return 1;
|
|
//}
|
|
|
|
int madefalse(int l,int i) {
|
|
int *ptr;
|
|
ptr = alleffectlits[i];
|
|
while(*ptr != -1) {
|
|
if(*ptr == feNEG(l)) return 1;
|
|
ptr = ptr + 1;
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
void removefalsified(eff *e,intset s) {
|
|
int *ptr;
|
|
while(e != NULL) {
|
|
ptr = e->effectlits;
|
|
while(*ptr != -1) { ISremove(feNEG(*ptr),s); ptr = ptr + 1; }
|
|
e = e->tl;
|
|
}
|
|
}
|
|
|
|
int localISmember0(int i,intset s) {
|
|
int j;
|
|
for(j=0;j<s->nOfEls;j++) {
|
|
if(s->elements[j] == i) return 1;
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
int localISmember1(int i,intset s) {
|
|
int j;
|
|
for(j=0;j<s->nOfEls;j++) {
|
|
if(s->elements[j] == i) return 1;
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
int localISmember2(int i,intset s) {
|
|
int j;
|
|
|
|
for(j=0;j<s->nOfEls;j++) {
|
|
if(s->elements[j] == i) return 1;
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
int localISmember3(int i,intset s) {
|
|
int j;
|
|
for(j=0;j<s->nOfEls;j++) {
|
|
if(s->elements[j] == i) return 1;
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
int wastruebefore(int l,intset before) {
|
|
int i;
|
|
// if(localISmember(l,before)) return 1;
|
|
/* Go through the relevant invariants. */
|
|
for(i=0;i<before->nOfEls;i++) {
|
|
if(before->elements[i] == l) return 1;
|
|
if(localISmember0(l,twolits[feNEG(before->elements[i])])) return 1;
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
void computeinvariants() {
|
|
int i,iteration,change,j,k;
|
|
eff *e;
|
|
int *il;
|
|
llist *prep;
|
|
intset trueones,ext;
|
|
int trueonesinitialized;
|
|
|
|
preprocess();
|
|
preprocess2();
|
|
|
|
ext = IScreateSize(10000);
|
|
|
|
trueones = IScreateSize(10000);
|
|
|
|
onelits = (int *)statmalloc(403,sizeof(int) * nOfAtoms);
|
|
twolits = (intset *)statmalloc(404,sizeof(intset) * nOfAtoms * 2);
|
|
|
|
for(i=0;i<nOfAtoms;i++) {
|
|
onelits[i] = initialstate[i];
|
|
twolits[fePLIT(i)] = IScreate();
|
|
twolits[feNLIT(i)] = IScreate();
|
|
}
|
|
|
|
if(flagNoInvariants) {
|
|
for(i=0;i<nOfAtoms;i++) {
|
|
onelits[i] = -1;
|
|
}
|
|
return;
|
|
}
|
|
|
|
printf("Invariants:");
|
|
|
|
iteration = 0;
|
|
change = 1;
|
|
|
|
while(change) {
|
|
|
|
printf(" %i",iteration); fflush(stdout);
|
|
change = 0;
|
|
|
|
for(i=0;i<nOfActions;i++) {
|
|
|
|
#ifdef DEBUG
|
|
printf("\nConsidering action %i:",i); fflush(stdout);
|
|
printaction(i);
|
|
printf("\n");
|
|
#endif
|
|
|
|
/* Both the precondition and the cond. eff. antecedents are tested without looking at the mutexes: would not usually make a difference! */
|
|
|
|
#ifdef CFMA
|
|
if(!ctruep(actions[i].cprecon)) continue; /* Not applicable (yet) */
|
|
#else
|
|
if(!truep(actions[i].precon)) continue; /* Not applicable (yet) */
|
|
#endif
|
|
|
|
/* Go through all first-time falsified literals:
|
|
weaken to all possible 2-literal clauses
|
|
|
|
Go through all 2-literal clauses with one disjunct falsified:
|
|
must the other disjunct be true?
|
|
*/
|
|
|
|
e = &(actions[i].effects);
|
|
|
|
/* prep is a list of known necessary preconditions and effects. */
|
|
prep = prepros[i];
|
|
|
|
while(e != NULL) {
|
|
|
|
trueonesinitialized = 0;
|
|
|
|
#ifdef CFMA
|
|
if(ctruep(e->ccondition)) {
|
|
#else
|
|
if(truep(e->condition)) {
|
|
#endif
|
|
|
|
/* In the following:
|
|
We have newly true literals in prep->after and
|
|
all true literals in trueones.
|
|
|
|
For every l in prep->after and m in trueones, -l V m
|
|
is an invariant.
|
|
These are all invariants involving -l.
|
|
|
|
We want to store all of these such that both -l and m
|
|
can have both value true and false.
|
|
*/
|
|
|
|
/* Go through effect literals */
|
|
|
|
il = e->effectlits;
|
|
|
|
while(*il != -1) {
|
|
int l;
|
|
l = *il;
|
|
il = il + 1;
|
|
|
|
/* See whether making literal l true falsifies something. */
|
|
|
|
if(onelits[feVAR(l)] == (l&1)) { /* Falsified a 1-literal */
|
|
|
|
if(trueonesinitialized == 0) {
|
|
|
|
trueonesinitialized = 1;
|
|
ISmakeempty(trueones);
|
|
|
|
/* literals true because they are in the precondition */
|
|
ISaddelements(prep->before,trueones);
|
|
|
|
/* literals true because a 2-literal clause is satisfied */
|
|
iITstart(prep->before);
|
|
while(iITnext(&j)) ISaddelements(twolits[feNEG(j)],trueones);
|
|
|
|
/* Remove literals that are falsified by this conditional effect
|
|
or possibly by other conditional effects. */
|
|
removefalsified(&(actions[i].effects),trueones);
|
|
|
|
/* Add literals that are made true. */
|
|
ISaddelements(prep->after,trueones);
|
|
}
|
|
|
|
change = 1;
|
|
|
|
onelits[feVAR(l)] = -1;
|
|
|
|
/* Add 2-literals -a | l */
|
|
|
|
iITstart(trueones);
|
|
while(iITnext(&k)) {
|
|
if(l != k && (onelits[feVAR(k)] == -1 || (localISmember1(k,prep->after) && onelits[feVAR(k)] == (k&1)))) {
|
|
ISinsertNODUP(k,twolits[feNEG(l)]);
|
|
ISinsertNODUP(feNEG(l),twolits[k]);
|
|
}
|
|
}
|
|
} else if(onelits[feVAR(l)] == -1) { /* Check preservation of 2-literal clauses */
|
|
|
|
/* Remove candidate 2-literal invariants which were falsified. */
|
|
|
|
IScopyto(twolits[feNEG(l)],ext);
|
|
|
|
iITstart(ext);
|
|
while(iITnext(&k)) {
|
|
if(!(localISmember2(k,prep->after)
|
|
|| (
|
|
wastruebefore(k,prep->before)
|
|
&&
|
|
!madefalse(k,i)
|
|
))) {
|
|
change = 1;
|
|
ISremove(k,twolits[feNEG(l)]);
|
|
ISremove(feNEG(l),twolits[k]);
|
|
}
|
|
}
|
|
|
|
/* If enabled a new state variable value (= invalidated
|
|
a candidate one-literal invariant), add new candidate
|
|
two-literal invariants that still remain true. */
|
|
|
|
iITstart(prep->after);
|
|
while(iITnext(&k)) {
|
|
if(l != k && onelits[feVAR(k)] == -1 && localISmember3(k,twolits[feNEG(l)])) {
|
|
ISinsert(feNEG(l),twolits[k]);
|
|
}
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
e = e->tl;
|
|
prep++;
|
|
}
|
|
|
|
// showInvariantsBrief();
|
|
}
|
|
|
|
iteration += 1;
|
|
}
|
|
|
|
for(i=0;i<nOfActions;i++) {
|
|
// ISfree(prepros[i].before);
|
|
// ISfree(prepros[i].after);
|
|
free(prepros[i]);
|
|
free(alleffectlits[i]);
|
|
}
|
|
|
|
free(prepros);
|
|
free(alleffectlits);
|
|
|
|
printf(" ");
|
|
|
|
if(flagShowInput) showInvariants();
|
|
|
|
}
|