#include "Formula.hpp"
#include "Clause.hpp"
#include "SubformulaIterator.hpp"
#include "Lib/Environment.hpp"
namespace Kernel {
using namespace std;
std::string Formula::DEFAULT_LABEL = "__unlabeled__";
void Formula::destroy ()
{
switch ( connective() ) {
case LITERAL:
delete static_cast<AtomicFormula*>(this);
return;
case AND:
case OR:
delete static_cast<JunctionFormula*>(this);
return;
case IMP:
case IFF:
case XOR:
delete static_cast<BinaryFormula*>(this);
return;
case NOT:
delete static_cast<NegatedFormula*>(this);
return;
case FORALL:
case EXISTS:
delete static_cast<QuantifiedFormula*>(this);
return;
case BOOL_TERM:
delete static_cast<BoolTermFormula*>(this);
case TRUE:
case FALSE:
delete this;
return;
case NAME:
delete static_cast<NamedFormula*>(this);
return;
case NOCONN:
ASSERTION_VIOLATION;
}
}
std::string Formula::toString (Connective c)
{
static std::string names [] =
{ "", "&", "|", "=>", "<=>", "<~>", "~", "!", "?", "$var", "$false", "$true","",""};
ASS_EQ(sizeof(names)/sizeof(std::string), NOCONN+1);
return names[(int)c];
}
std::string Formula::toString () const
{
std::string res;
typedef struct {
bool wrapInParenthesis;
Connective renderConnective; const Formula* theFormula; } Todo;
Stack<Todo> stack;
stack.push({false,NOCONN,this});
while (stack.isNonEmpty()) {
Todo todo = stack.pop();
{
std::string con = toString(todo.renderConnective);
if (con != "") {
res += " "+con+" ";
}
}
const Formula* f = todo.theFormula;
if (!f) {
res += ")";
continue;
}
if (todo.wrapInParenthesis) {
res += "(";
stack.push({false,NOCONN,nullptr}); }
Connective c = f->connective();
switch (c) {
case NAME:
res += static_cast<const NamedFormula*>(f)->name();
continue;
case LITERAL: {
auto af = static_cast<const AtomicFormula *>(f);
res += af->literal()->toString(af->flipForPrinting);
continue;
}
case AND:
case OR:
{
const FormulaList* fs = f->args();
ASS (FormulaList::length(fs) >= 2);
while (FormulaList::isNonEmpty(fs)) {
const Formula* arg = fs->head();
fs = fs->tail();
stack.push({arg->parenthesesRequired(c),FormulaList::isNonEmpty(fs) ? c : NOCONN,arg});
}
continue;
}
case IMP:
case IFF:
case XOR:
stack.push({f->right()->parenthesesRequired(c),c,f->right()}); stack.push({f->left()->parenthesesRequired(c),NOCONN,f->left()});
continue;
case NOT:
{
res += toString(c);
const Formula* arg = f->uarg();
stack.push({arg->parenthesesRequired(c),NOCONN,arg});
continue;
}
case FORALL:
case EXISTS:
{
res += toString(c) + " [";
VList::Iterator vs(f->vars());
SList::Iterator ss(f->sorts());
bool hasSorts = f->sorts();
bool first=true;
while (vs.hasNext()) {
int var = vs.next();
if (!first) {
res += ",";
}
res += Term::variableToString(var);
TermList t;
if (hasSorts) {
ASS(ss.hasNext());
t = ss.next();
if (t != AtomicSort::defaultSort()) {
res += " : " + t.toString();
}
} else if (SortHelper::tryGetVariableSort(var, const_cast<Formula*>(f),t) && t != AtomicSort::defaultSort()) {
res += " : " + t.toString();
}
first = false;
}
res += "] : ";
const Formula* arg = f->qarg();
stack.push({arg->parenthesesRequired(c),NOCONN,arg});
continue;
}
case BOOL_TERM: {
std::string term = f->getBooleanTerm().toString();
res += env.options->showFOOL() ? "$formula{" + term + "}" : term;
continue;
}
case TRUE:
case FALSE:
res += toString(c);
continue;
case NOCONN:
ASSERTION_VIOLATION;
}
}
return res;
}
bool Formula::parenthesesRequired (Connective outer) const
{
switch (connective())
{
case LITERAL:
case NOT:
case FORALL:
case EXISTS:
case BOOL_TERM:
case TRUE:
case FALSE:
case NAME:
return false;
case OR:
case AND:
case IMP:
case IFF:
case XOR:
return true;
case NOCONN:
ASSERTION_VIOLATION;
}
ASSERTION_VIOLATION;
}
VList* Formula::boundVariables () const
{
VList* res = VList::empty();
SubformulaIterator sfit(const_cast<Formula*>(this));
while(sfit.hasNext()) {
Formula* sf = sfit.next();
if(sf->connective() == FORALL || sf->connective() == EXISTS) {
VList* qvars = sf->vars();
VList* qvCopy = VList::copy(qvars);
res = VList::concat(qvCopy, res);
}
}
return res;
}
unsigned Formula::weight() const
{
unsigned result=0;
SubformulaIterator fs(const_cast<Formula*>(this));
while (fs.hasNext()) {
const Formula* f = fs.next();
switch (f->connective()) {
case LITERAL:
result += f->literal()->weight();
break;
default:
result++;
break;
}
}
return result;
}
Formula* JunctionFormula::generalJunction(Connective c, FormulaList* args)
{
if(!args) {
if(c==AND) {
return new Formula(true);
}
else {
ASS_EQ(c,OR);
return new Formula(false);
}
}
if(!args->tail()) {
return FormulaList::pop(args);
}
return new JunctionFormula(c, args);
}
Color Formula::getColor()
{
SubformulaIterator si(this);
while(si.hasNext()) {
Formula* f=si.next();
if(f->connective()!=LITERAL) {
continue;
}
if(f->literal()->color()!=COLOR_TRANSPARENT) {
return f->literal()->color();
}
}
return COLOR_TRANSPARENT;
}
bool Formula::getSkip()
{
SubformulaIterator si(this);
while(si.hasNext()) {
Formula* f=si.next();
if(f->connective()!=LITERAL) {
continue;
}
if(!f->literal()->skip()) {
return false;
}
}
return true;
}
Formula* Formula::trueFormula()
{
static Formula* res = new Formula(true);
return res;
}
Formula* Formula::falseFormula()
{
static Formula* res = new Formula(false);
return res;
}
Formula* Formula::createITE(Formula* condition, Formula* thenArg, Formula* elseArg)
{
TermList thenTerm(Term::createFormula(thenArg));
TermList elseTerm(Term::createFormula(elseArg));
TermList iteTerm(Term::createITE(condition, thenTerm, elseTerm, AtomicSort::boolSort()));
return new BoolTermFormula(iteTerm);
}
Formula* Formula::createLet(Formula* binder, Formula* body)
{
TermList bodyTerm(Term::createFormula(body));
TermList letTerm(Term::createLet(binder, bodyTerm, AtomicSort::boolSort()));
return new BoolTermFormula(letTerm);
}
Formula* Formula::createDefinition(Term* lhs, TermList rhs, VList* uVars)
{
auto sort = lhs->isBoolean() ? AtomicSort::boolSort() : SortHelper::getResultSort(lhs);
auto lit = Literal::create(env.signature->getDefPred(), true, { sort, TermList(lhs), rhs });
Formula* res = new AtomicFormula(lit);
if (uVars) {
res = new QuantifiedFormula(Connective::FORALL, uVars, nullptr, res);
}
return res;
}
Formula* Formula::quantify(Formula* f)
{
DHMap<unsigned,TermList> tMap;
SortHelper::collectVariableSorts(f,tMap,true);
VList::FIFO quantifiedVars;
SList::FIFO theirSorts;
DHMap<unsigned,TermList>::Iterator tmit(tMap);
while(tmit.hasNext()) {
unsigned v;
TermList s;
tmit.next(v, s);
if(s.isTerm() && s.term()->isSuper()){
quantifiedVars.pushFront(v);
theirSorts.pushFront(s);
} else {
quantifiedVars.pushBack(v);
theirSorts.pushBack(s);
}
}
if(!quantifiedVars.empty()) {
f = new QuantifiedFormula(FORALL, quantifiedVars.list(), theirSorts.list(), f);
}
return f;
}
Formula* Formula::fromClause(Clause* cl, bool closed)
{
FormulaList* resLst=0;
unsigned clen=cl->length();
for(unsigned i=0;i<clen;i++) {
Formula* lf=new AtomicFormula((*cl)[i]);
FormulaList::push(lf, resLst);
}
Formula* res=JunctionFormula::generalJunction(OR, resLst);
return closed ? Formula::quantify(res) : res;
}
Formula* BoolTermFormula::create(TermList ts)
{
if (ts.isVar()) {
return new BoolTermFormula(ts);
}
Term* term = ts.term();
if (term->isSpecial()) {
Term::SpecialTermData *sd = term->getSpecialData();
switch (sd->specialFunctor()) {
case SpecialFunctor::FORMULA:
return sd->getFormula();
default:
return new BoolTermFormula(ts);
}
} else {
unsigned functor = term->functor();
if (env.signature->isFoolConstantSymbol(true, functor)) {
return new Formula(true);
}
if (env.signature->isFoolConstantSymbol(false, functor)) {
return new Formula(false);
}
return new BoolTermFormula(ts);
}
}
std::ostream& operator<< (std::ostream& out, const Formula& f)
{
return out << f.toString();
}
std::ostream& operator<< (std::ostream& out, const Formula* f)
{
return out << f->toString();
}
}