std::vector<KFormula*> KFormula::getAtoms(KFormula* f) { std::vector<KFormula*> atoms; std::deque<KFormula*> formulae; formulae.push_back(f); while (!formulae.empty()) { KFormula* formula = formulae.front(); formulae.pop_front(); switch (formula->getop()) { case KFormula::AP: atoms.push_back(formula); break; case KFormula::BOX: atoms.push_back(formula); formulae.push_back(&(formula->getleft())); break; case KFormula::NOT: // Immediately continue with the unnegated formula. formulae.push_front(&(formula->getleft())); break; case KFormula::AND:// Fall through case KFormula::OR: // Breadth-first add from both sides. formulae.push_back(&(formula->getleft())); formulae.push_back(&(formula->getright())); break; case KFormula::TRUE: break; case KFormula::FALSE: break; case KFormula::DIA: assert(false && "Atom adding not defined for <>."); case KFormula::IMP: assert(false && "Atom adding not defined for =>."); case KFormula::EQU: assert(false && "Atom adding not defined for <=>."); default: assert(false && "Defaulted out of complete switch"); } } return atoms; }
KFormula* KFormula::parseRest(const char*& str) { while(isspace(*str)) ++str; KFormula *left; if(*str == '('){ ++str; left = parseEQU(str); while(isspace(*str)) ++str; assert(*str == ')'); ++str; return left; } else if (strncmp(str,"<", 1) == 0 && (isalnum(*(str + 1)) || *(str+1) == '-')) { size_t n = 1;// "<" if (*(str+1) == '-') ++n; while(isalnum(*(str+n))) ++n; std::string roleString(str+1, n - 1); ++n;// ">" str += n; left = parseRest(str); left = new KFormula(KFormula::DIA,left,NULL); left->setprop(roleString); return left; } else if (strncmp(str,"<>", 2) == 0) { str += 2; left = parseRest(str); left = new KFormula(KFormula::DIA,left,NULL); return left; } else if (strncmp(str,"[", 1) == 0 && (isalnum(*(str + 1)) || *(str+1) == '-')) { size_t n = 1;// "[" if (*(str+1) == '-') ++n; while(isalnum(*(str+n))) ++n; std::string roleString(str+1, n - 1); ++n;// "]" str += n; left = parseRest(str); left = new KFormula(KFormula::BOX,left,NULL); left->setprop(roleString); return left; }else if (strncmp(str,"[]",2) == 0) { str += 2; left = parseRest(str); left = new KFormula(KFormula::BOX,left,NULL); return left; } else if (*str=='~') { ++str; left = parseRest(str); left = new KFormula(KFormula::NOT,left,NULL); return left; } else if (strncmp(str,"True",4)==0) { str += 4; return new KFormula(true); } else if (strncmp(str,"False",5)==0) { str += 5; return new KFormula(false); } else if (isalpha(*str) || *str == '_') { size_t n = 1; while(isalnum(*(str+n)) || *(str+n) == '_') ++n; left = new KFormula(std::string(str,n)); str += n; return left; } assert(false && "Could not parse input"); // Must not reach here }
/* * BoxNNF: NNF with the following exceptions: * BoxNNF(~[]phi) = ~BoxNNF([]phi) * BoxNNF(<>phi) = ~[]BoxNNF(~phi) * This is to normalise the modalities so that we don't get separate BDD * variables for <>~phi and []phi. These should share the same variable, * as ~<>~phi = []phi. */ KFormula* KFormula::toBoxNNF(KFormula* f) { switch (f->getop()) { case KFormula::AP: return f; case KFormula::AND: return new KFormula(KFormula::AND, toBoxNNF(&(f->getleft())), toBoxNNF(&(f->getright()))); case KFormula::OR: return new KFormula(KFormula::OR, toBoxNNF(&(f->getleft())), toBoxNNF(&(f->getright()))); case KFormula::BOX: {KFormula* tmpf = new KFormula(KFormula::BOX, toBoxNNF(&(f->getleft())), NULL); tmpf->setprop(f->getprop()); return tmpf;} case KFormula::DIA:// BoxNNF(<>phi) = ~[]BoxNNF(~phi) {KFormula* tmpf = new KFormula(KFormula::BOX, toBoxNNF(new KFormula(KFormula::NOT, &(f->getleft()), NULL)), NULL); tmpf->setprop(f->getprop());// TODO this multimodal hack is really ugly... return new KFormula(KFormula::NOT, tmpf, NULL);} case KFormula::TRUE: return f; case KFormula::FALSE: return f; case KFormula::IMP: return toBoxNNF(new KFormula(KFormula::OR, new KFormula(KFormula::NOT, &(f->getleft()), NULL), &(f->getright()))); case KFormula::NOT: switch (f->getleft().getop()) { case KFormula::AP: return f; case KFormula::AND: return new KFormula(KFormula::OR, toBoxNNF(new KFormula(KFormula::NOT, &(f->getleft().getleft()), NULL)), toBoxNNF(new KFormula(KFormula::NOT, &(f->getleft().getright()), NULL))); case KFormula::OR: return new KFormula(KFormula::AND, toBoxNNF(new KFormula(KFormula::NOT, &(f->getleft().getleft()), NULL)), toBoxNNF(new KFormula(KFormula::NOT, &(f->getleft().getright()), NULL))); case KFormula::BOX:// BoxNNF(~[]phi) = ~[]BoxNNF(phi) {KFormula* tmpf = new KFormula(KFormula::BOX, toBoxNNF(&(f->getleft().getleft())), NULL); tmpf->setprop(f->getleft().getprop()); return new KFormula(KFormula::NOT, tmpf, NULL);} case KFormula::DIA: {KFormula* tmpf = new KFormula(KFormula::BOX, toBoxNNF(new KFormula(KFormula::NOT, &(f->getleft().getleft()), NULL)), NULL); tmpf->setprop(f->getleft().getprop()); return tmpf;} case KFormula::TRUE: return new KFormula(false); case KFormula::FALSE: return new KFormula(true); case KFormula::IMP: return toBoxNNF(new KFormula(KFormula::AND, &(f->getleft().getleft()), new KFormula(KFormula::NOT, &(f->getleft().getright()), NULL))); case KFormula::NOT: return toBoxNNF(&(f->getleft().getleft())); case KFormula::EQU: return new KFormula(KFormula::AND, new KFormula(KFormula::OR, toBoxNNF(new KFormula(KFormula::NOT, &(f->getleft().getleft()), NULL)), toBoxNNF(new KFormula(KFormula::NOT, &(f->getleft().getright()), NULL))), new KFormula(KFormula::OR, toBoxNNF(&(f->getleft().getleft())), toBoxNNF(&(f->getleft().getright())))); default: assert(false && "Defaulted out of complete switch."); } case KFormula::EQU: return new KFormula(KFormula::OR, new KFormula(KFormula::AND, toBoxNNF(&(f->getleft())), toBoxNNF(&(f->getright()))), new KFormula(KFormula::AND, toBoxNNF(new KFormula(KFormula::NOT, &(f->getleft()), NULL)), toBoxNNF(new KFormula(KFormula::NOT, &(f->getright()), NULL)))); default: assert(false && "Defaulted out of complete switch."); } exit(0); }