translator.cpp

Go to the documentation of this file.
00001 /*****************************************************************************/
00002 /*!
00003  * \file translator.cpp
00004  * \brief Description: Code for translation between languages
00005  * 
00006  * Author: Clark Barrett
00007  * 
00008  * Created: Sat Jun 25 18:06:52 2005
00009  *
00010  * <hr>
00011  *
00012  * License to use, copy, modify, sell and/or distribute this software
00013  * and its documentation for any purpose is hereby granted without
00014  * royalty, subject to the terms and conditions defined in the \ref
00015  * LICENSE file provided with this distribution.
00016  * 
00017  * <hr>
00018  * 
00019  */
00020 /*****************************************************************************/
00021 
00022 
00023 #include "translator.h"
00024 #include "expr.h"
00025 #include "theory_core.h"
00026 #include "theory_uf.h"
00027 #include "theory_arith.h"
00028 #include "theory_bitvector.h"
00029 #include "theory_array.h"
00030 #include "theory_quant.h"
00031 #include "theory_records.h"
00032 #include "theory_simulate.h"
00033 #include "theory_datatype.h"
00034 #include "theory_datatype_lazy.h"
00035 #include "smtlib_exception.h"
00036 
00037 
00038 using namespace std;
00039 using namespace CVC3;
00040 
00041 
00042 string Translator::fileToSMTLIBIdentifier(const string& filename)
00043 {
00044   string tmpName;
00045   string::size_type pos = filename.rfind("/");
00046   if (pos == string::npos) {
00047     tmpName = filename;
00048   }
00049   else {
00050     tmpName = filename.substr(pos+1);
00051   }
00052   char c = tmpName[0];
00053   string res;
00054   if ((c < 'A' || c > 'Z') && (c < 'a' || c > 'z')) {
00055     res = "B_";
00056   }
00057   for (unsigned i = 0; i < tmpName.length(); ++i) {
00058     c = tmpName[i];
00059     if ((c < 'A' || c > 'Z') && (c < 'a' || c > 'z') &&
00060         (c < '0' || c > '9') && (c != '.' && c != '_')) {
00061       c = '_';
00062     }
00063     res += c;
00064   }
00065   return res;
00066 }
00067 
00068 
00069 Expr Translator::preprocessRec(const Expr& e, ExprMap<Expr>& cache)
00070 {
00071   ExprMap<Expr>::iterator i(cache.find(e));
00072   if(i != cache.end()) {
00073     return (*i).second;
00074   }
00075 
00076   if (e.isClosure()) {
00077     Expr newBody = preprocessRec(e.getBody(), cache);
00078     Expr e2(e);
00079     if (newBody != e.getBody()) {
00080       e2 = d_em->newClosureExpr(e.getKind(), e.getVars(), newBody);
00081     }
00082     d_theoryCore->theoryOf(e2)->setUsed();
00083     cache[e] = e2;
00084     return e2;
00085   }
00086 
00087   Expr e2(e);
00088   vector<Expr> children;
00089   bool diff = false;
00090 
00091   for(int k = 0; k < e.arity(); ++k) {
00092     // Recursively preprocess the kids
00093     Expr child = preprocessRec(e[k], cache);
00094     if (child != e[k]) diff = true;
00095     children.push_back(child);
00096   }
00097   if (diff) {
00098     e2 = Expr(e.getOp(), children);
00099   }
00100 
00101   Rational r;
00102   switch (e2.getKind()) {
00103     case APPLY:
00104       // Expand lambda applications
00105       if (e2.getOpKind() == LAMBDA) {
00106         Expr lambda(e2.getOpExpr());
00107         Expr body(lambda.getBody());
00108         const vector<Expr>& vars = lambda.getVars();
00109         FatalAssert(vars.size() == (size_t)e2.arity(), 
00110                     "wrong number of arguments applied to lambda\n");
00111         body = body.substExpr(vars, e2.getKids());
00112         e2 = preprocessRec(body, cache);
00113       }
00114       break;
00115     case EQ:
00116       if (d_theoryArith->getBaseType(e2[0]) != d_theoryArith->realType())
00117         break;
00118       goto arith_rewrites;
00119 
00120     case UMINUS:
00121       if (d_theoryArith->isSyntacticRational(e2, r)) {
00122         e2 = preprocessRec(d_em->newRatExpr(r), cache);
00123         break;
00124       }
00125       goto arith_rewrites;
00126 
00127     case DIVIDE:
00128       if (d_theoryArith->isSyntacticRational(e2, r)) {
00129         e2 = preprocessRec(d_em->newRatExpr(r), cache);
00130         break;
00131       }
00132       else if (d_convertArith && e2[1].isRational()) {
00133         r = e2[1].getRational();
00134         if (r != 0) {
00135           e2 = d_em->newRatExpr(1/r) * e2[0];
00136           e2 = preprocessRec(e2, cache);
00137           break;
00138         }
00139       }
00140       goto arith_rewrites;
00141 
00142     case PLUS:
00143       if (d_convertArith) {
00144         // Flatten and combine constants
00145         vector<Expr> terms;
00146         bool changed = false;
00147         r = 0;
00148         Expr::iterator i = e2.begin(), iend = e2.end();
00149         for(; i!=iend; ++i) {
00150           if ((*i).getKind() == PLUS) {
00151             changed = true;
00152             Expr::iterator i2 = (*i).begin(), i2end = (*i).end();
00153             for (; i2 != i2end; ++i2) {
00154               if ((*i2).isRational()) r += (*i2).getRational();
00155               else terms.push_back(*i2);
00156             }
00157           }
00158           else {
00159             if ((*i).isRational()) {
00160               if (r != 0) changed = true;
00161               r += (*i).getRational();
00162             }
00163             else terms.push_back(*i);
00164           }
00165         }
00166         if (terms.size() == 0) {
00167           e2 = preprocessRec(d_em->newRatExpr(r), cache);
00168           break;
00169         }
00170         else if (terms.size() == 1) {
00171           if (r == 0) {
00172             e2 = terms[0];
00173             break;
00174           }
00175           else if (r < 0) {
00176             e2 = preprocessRec(Expr(MINUS, terms[0], d_em->newRatExpr(-r)), cache);
00177             break;
00178           }
00179         }
00180         if (changed) {
00181           if (r != 0) terms.push_back(d_em->newRatExpr(r));
00182           e2 = preprocessRec(Expr(PLUS, terms), cache);
00183           break;
00184         }
00185       }
00186       goto arith_rewrites;
00187 
00188     case POW:
00189       if (d_convertArith && e2[0].isRational()) {
00190         r = e2[0].getRational();
00191         if (r.isInteger() && r.getNumerator() == 2) {
00192           e2 = preprocessRec(e2[1] * e2[1], cache);
00193           break;
00194         }
00195       }
00196       // fall through
00197 
00198     case LT:
00199     case GT:
00200     case LE:
00201     case GE:
00202     case MINUS:
00203     case MULT:
00204     case INTDIV:
00205     case MOD:
00206 
00207   arith_rewrites:
00208       if (d_iteLiftArith) {
00209         diff = false;
00210         children.clear();
00211         vector<Expr> children2;
00212         Expr cond;
00213         for (int k = 0; k < e2.arity(); ++k) {
00214           if (e2[k].getKind() == ITE && !diff) {
00215             diff = true;
00216             cond = e2[k][0];
00217             children.push_back(e2[k][1]);
00218             children2.push_back(e2[k][2]);
00219           }
00220           else {
00221             children.push_back(e2[k]);
00222             children2.push_back(e2[k]);
00223           }
00224         }
00225         if (diff) {
00226           Expr thenpart = Expr(e2.getOp(), children);
00227           Expr elsepart = Expr(e2.getOp(), children2);
00228           e2 = cond.iteExpr(thenpart, elsepart);
00229           e2 = preprocessRec(e2, cache);
00230           break;
00231         }
00232       }
00233 
00234       if (d_convertToDiff != "" && d_theoryArith->isAtomicArithFormula(e2)) {
00235         Expr e3 = d_theoryArith->rewriteToDiff(e2);
00236         if (e2 != e3) {
00237           DebugAssert(e3 == d_theoryArith->rewriteToDiff(e3), "Expected idempotent rewrite");
00238           e2 = preprocessRec(e3, cache);
00239         }
00240         break;
00241       }
00242 
00243       break;
00244     default:
00245       break;
00246   }
00247 
00248   // Figure out language
00249   switch (e2.getKind()) {
00250     case RATIONAL_EXPR:
00251       r = e2.getRational();
00252       if (r.isInteger()) {
00253         d_intConstUsed = true;
00254       }
00255       else {
00256         d_realUsed = true;
00257       }
00258       if (d_langUsed == NOT_USED) d_langUsed = TERMS_ONLY;
00259       break;
00260     case IS_INTEGER:
00261       d_unknown = true;
00262       break;
00263     case PLUS: {
00264       if (e2.arity() == 2) {
00265         int nonconst = 0, isconst = 0;
00266         Expr::iterator i = e2.begin(), iend = e2.end();
00267         for(; i!=iend; ++i) {
00268           if ((*i).isRational()) {
00269             if ((*i).getRational() <= 0) {
00270               d_UFIDL_ok = false;
00271               break;
00272             }
00273             else ++isconst;
00274           }
00275           else ++nonconst;
00276         }
00277         if (nonconst > 1 || isconst > 1)
00278           d_UFIDL_ok = false;
00279       }
00280       else d_UFIDL_ok = false;
00281       if (d_langUsed == NOT_USED) d_langUsed = TERMS_ONLY;
00282       break;
00283     }
00284     case MINUS:
00285       if (!e2[1].isRational() || e2[1].getRational() <= 0) {
00286         d_UFIDL_ok = false;
00287       }
00288       if (d_langUsed == NOT_USED) d_langUsed = TERMS_ONLY;
00289       break;
00290     case UMINUS:
00291       d_UFIDL_ok = false;
00292       if (d_langUsed == NOT_USED) d_langUsed = TERMS_ONLY;
00293       break;
00294     case MULT: {
00295       d_UFIDL_ok = false;
00296       if (d_langUsed == NONLINEAR) break;
00297       d_langUsed = LINEAR;
00298       bool nonconst = false;
00299       for (int i=0; i!=e2.arity(); ++i) {
00300         if (e2[i].isRational()) continue;
00301         if (nonconst) {
00302           d_langUsed = NONLINEAR;
00303           break;
00304         }
00305         nonconst = true;
00306       }
00307       break;
00308     }
00309     case POW:
00310     case DIVIDE:
00311       d_unknown = true;
00312       break;
00313 
00314     case EQ:
00315       if (d_theoryArith->getBaseType(e2[0]) != d_theoryArith->realType())
00316         break;
00317     case LT:
00318     case GT:
00319     case LE:
00320     case GE:
00321       if (d_langUsed >= LINEAR) break;
00322       if (!d_theoryArith->isAtomicArithFormula(e2)) {
00323         d_langUsed = LINEAR;
00324         break;
00325       }
00326       if (e2[0].getKind() == MINUS &&
00327           d_theoryArith->isLeaf(e2[0][0]) &&
00328           d_theoryArith->isLeaf(e2[0][1]) &&
00329           e2[1].isRational()) {
00330         d_langUsed = DIFF_ONLY;
00331         break;
00332       }
00333       if (d_theoryArith->isLeaf(e2[0]) &&
00334           d_theoryArith->isLeaf(e2[1])) {
00335         d_langUsed = DIFF_ONLY;
00336         break;
00337       }
00338       d_langUsed = LINEAR;
00339       break;
00340     default:
00341       break;
00342   }
00343 
00344   d_theoryCore->theoryOf(e2)->setUsed();
00345   
00346   cache[e] = e2;
00347   return e2;
00348 }
00349 
00350 
00351 Expr Translator::preprocess(const Expr& e, ExprMap<Expr>& cache)
00352 {
00353   Expr result;
00354   try {
00355     result = preprocessRec(e, cache);
00356   } catch (SmtlibException& ex) {
00357     cerr << "Error while processing the formula:\n"
00358          << e.toString() << endl;
00359     throw ex;
00360   }
00361   return result;
00362 }
00363 
00364 
00365 Expr Translator::preprocess2Rec(const Expr& e, ExprMap<Expr>& cache, Type desiredType)
00366 {
00367   ExprMap<Expr>::iterator i(cache.find(e));
00368   if(i != cache.end()) {
00369     if ((desiredType.isNull() &&
00370          (*i).second.getType() != d_theoryArith->realType()) ||
00371         (*i).second.getType() == desiredType) {
00372       return (*i).second;
00373     }
00374   }
00375 
00376   if (e.isClosure()) {
00377     Expr newBody = preprocess2Rec(e.getBody(), cache, Type());
00378     Expr e2(e);
00379     if (newBody != e.getBody()) {
00380       e2 = d_em->newClosureExpr(e.getKind(), e.getVars(), newBody);
00381     }
00382     cache[e] = e2;
00383     return e2;
00384   }
00385 
00386   bool forceReal = false;
00387   if (desiredType == d_theoryArith->intType() &&
00388       e.getType() != d_theoryArith->intType()) {
00389     d_unknown = true;
00390 //     throw SmtlibException("Unable to separate int and real "+
00391 //                           e.getType().getExpr().toString()+
00392 //                           "\n\nwhile processing the term:\n"+
00393 //                           e.toString(PRESENTATION_LANG));
00394   }
00395 
00396   // Try to force type-compliance
00397   switch (e.getKind()) {
00398     case EQ:
00399     case LT:
00400     case GT:
00401     case LE:
00402     case GE:
00403       if (e[0].getType() != e[1].getType()) {
00404         if (e[0].getType() != d_theoryArith->intType() &&
00405             e[1].getType() != d_theoryArith->intType()) {
00406           d_unknown = true;
00407           throw SmtlibException("Expected each side to be REAL or INT, but we got lhs: "+
00408                                 e[0].getType().getExpr().toString()+" and rhs: "+
00409                                 e[1].getType().getExpr().toString()+
00410                                 "\n\nwhile processing the term:\n"+
00411                                 e.toString());
00412         }
00413         forceReal = true;
00414         break;
00415       case ITE:
00416       case UMINUS:
00417       case PLUS:
00418       case MINUS:
00419       case MULT:
00420         if (desiredType == d_theoryArith->realType())
00421           forceReal = true;
00422         break;
00423       case DIVIDE:
00424         forceReal = true;
00425         break;
00426       default:
00427         break;
00428     }
00429   }
00430 
00431   Expr e2(e);
00432   vector<Expr> children;
00433   bool diff = false;
00434 
00435   Type funType;
00436   if (e.isApply()) {
00437     funType = e.getOpExpr().getType();
00438     if (funType.getExpr().getKind() == ANY_TYPE) funType = Type();
00439   }
00440 
00441   for(int k = 0; k < e.arity(); ++k) {
00442     Type t;
00443     if (forceReal && e[k].getType() == d_theoryArith->intType())
00444       t = d_theoryArith->realType();
00445     else if (!funType.isNull()) t = funType[k];
00446     // Recursively preprocess the kids
00447     Expr child = preprocess2Rec(e[k], cache, t);
00448     if (child != e[k]) diff = true;
00449     children.push_back(child);
00450   }
00451   if (diff) {
00452     e2 = Expr(e.getOp(), children);
00453   }
00454   else if (e2.getKind() == RATIONAL_EXPR) {
00455     if (e2.getType() == d_theoryArith->realType() ||
00456         (e2.getType() == d_theoryArith->intType() &&
00457          desiredType == d_theoryArith->realType()))
00458       e2 = Expr(REAL_CONST, e2);
00459   }
00460   if (!desiredType.isNull() && e2.getType() != desiredType) {
00461     d_unknown = true;
00462     throw SmtlibException("Type error: expected "+
00463                           desiredType.getExpr().toString()+
00464                           " but instead got "+
00465                           e2.getType().getExpr().toString()+
00466                           "\n\nwhile processing term:\n"+
00467                           e.toString());
00468   }
00469 
00470   cache[e] = e2;
00471   return e2;
00472 }
00473 
00474 
00475 Expr Translator::preprocess2(const Expr& e, ExprMap<Expr>& cache)
00476 {
00477   Expr result;
00478   try {
00479     result = preprocess2Rec(e, cache, Type());
00480   } catch (SmtlibException& ex) {
00481     cerr << "Error while processing the formula:\n"
00482          << e.toString() << endl;
00483     throw ex;
00484   }
00485   return result;
00486 }
00487 
00488 
00489 
00490 
00491 bool Translator::containsArray(const Expr& e)
00492 {
00493   if (e.getKind() == ARRAY) return true;
00494   Expr::iterator i = e.begin(), iend=e.end();
00495   for(; i!=iend; ++i) if (containsArray(*i)) return true;
00496   return false;
00497 }
00498 
00499 
00500 Translator::Translator(ExprManager* em,
00501                        const bool& translate,
00502                        const bool& real2int,
00503                        const bool& convertArith,
00504                        const string& convertToDiff,
00505                        bool iteLiftArith,
00506                        const string& expResult,
00507                        const string& category,
00508                        bool convertArray,
00509                        bool combineAssump)
00510   : d_em(em), d_translate(translate),
00511     d_real2int(real2int),
00512     d_convertArith(convertArith),
00513     d_convertToDiff(convertToDiff),
00514     d_iteLiftArith(iteLiftArith),
00515     d_expResult(expResult),
00516     d_category(category),
00517     d_convertArray(convertArray),
00518     d_combineAssump(combineAssump),
00519     d_dump(false), d_dumpFileOpen(false),
00520     d_intIntArray(false), d_intRealArray(false), d_intIntRealArray(false),
00521     d_ax(false), d_unknown(false),
00522     d_realUsed(false), d_intUsed(false), d_intConstUsed(false),
00523     d_langUsed(NOT_USED), d_UFIDL_ok(true), d_arithUsed(false),
00524     d_zeroVar(NULL)
00525 {}
00526 
00527 
00528 bool Translator::start(const string& dumpFile)
00529 {
00530   if (d_translate && d_em->getOutputLang() == SMTLIB_LANG) {
00531     d_dump = true;
00532     if (dumpFile == "") {
00533       d_osdump = &cout;
00534     }
00535     else {
00536       d_osdumpFile.open(dumpFile.c_str());
00537       if(!d_osdumpFile)
00538         throw Exception("cannot open a log file: "+dumpFile);
00539       else {
00540         d_dumpFileOpen = true;
00541         d_osdump = &d_osdumpFile;
00542       }
00543     }
00544     *d_osdump <<
00545       "(benchmark " << fileToSMTLIBIdentifier(dumpFile) << endl <<
00546       "  :source {" << endl;
00547     string tmpName;
00548     string::size_type pos = dumpFile.rfind("/");
00549     if (pos == string::npos) {
00550       tmpName = "README";
00551     }
00552     else {
00553       tmpName = dumpFile.substr(0,pos+1) + "README";
00554     }
00555     d_tmpFile.open(tmpName.c_str());
00556     char c;
00557     if (d_tmpFile.is_open()) {
00558       d_tmpFile.get(c);
00559       while (!d_tmpFile.eof()) {
00560         if (c == '{' || c == '}') *d_osdump << '\\';
00561         *d_osdump << c;
00562         d_tmpFile.get(c);
00563       }
00564       d_tmpFile.close();
00565     }
00566     else {
00567       *d_osdump << "Source unknown";
00568     }
00569     *d_osdump << endl;// <<
00570     //        "This benchmark was automatically translated into SMT-LIB format from" << endl <<
00571     //        "CVC format using CVC3" << endl;
00572     *d_osdump << "}" << endl;
00573 
00574   }
00575   else {
00576     if (dumpFile == "") {
00577       if (d_translate) {
00578         d_osdump = &cout;
00579         d_dump = true;
00580       }
00581     }
00582     else {
00583       d_osdumpFile.open(dumpFile.c_str());
00584       if(!d_osdumpFile)
00585         throw Exception("cannot open a log file: "+dumpFile);
00586       else {
00587         d_dump = true;
00588         d_dumpFileOpen = true;
00589         d_osdump = &d_osdumpFile;
00590       }
00591     }
00592   }
00593   return d_dump;
00594 }
00595 
00596 
00597 void Translator::dump(const Expr& e, bool dumpOnly)
00598 {
00599   DebugAssert(d_dump, "dump called unexpectedly");
00600   if (!dumpOnly || !d_translate) {
00601     if (d_convertArray && e.getKind() == CONST &&
00602         e.arity() == 2) {
00603       if (e[1].getKind() == ARRAY) {
00604         if (containsArray(e[1][0]) ||
00605             containsArray(e[1][1])) {
00606           throw Exception("convertArray failed because of nested arrays in"+
00607                           e[1].toString());
00608         }
00609         Expr funType = Expr(ARROW, e[1][0], e[1][1]);
00610         Expr outExpr = Expr(CONST, e[0], funType);
00611         if (d_translate && d_em->getOutputLang() == SMTLIB_LANG) {
00612           d_dumpExprs.push_back(outExpr);
00613         }
00614         else {
00615           *d_osdump << outExpr << endl;
00616         }
00617       }
00618       else if (containsArray(e[1])) {
00619         throw Exception("convertArray failed becauase of use of arrays in"+
00620                         e[1].toString());
00621       }
00622       else if (d_translate && d_em->getOutputLang() == SMTLIB_LANG) {
00623         d_dumpExprs.push_back(e);
00624       }
00625       else *d_osdump << e << endl;
00626     }
00627     else if (d_translate && d_em->getOutputLang() == SMTLIB_LANG) {
00628       d_dumpExprs.push_back(e);
00629     }
00630     else *d_osdump << e << endl;
00631   }
00632 }
00633 
00634 
00635 bool Translator::dumpAssertion(const Expr& e)
00636 {
00637   Expr outExpr = Expr(ASSERT, e);
00638   if (d_translate && d_em->getOutputLang() == SMTLIB_LANG) {
00639     d_dumpExprs.push_back(outExpr);
00640   }
00641   else {
00642     *d_osdump << outExpr << endl;
00643   }
00644   return d_translate;
00645 }
00646 
00647 
00648 bool Translator::dumpQuery(const Expr& e)
00649 {
00650   Expr outExpr = Expr(QUERY, e);
00651   if (d_translate && d_em->getOutputLang() == SMTLIB_LANG) {
00652     d_dumpExprs.push_back(outExpr);
00653   }
00654   else {
00655     *d_osdump << outExpr << endl;
00656   }
00657   return d_translate;
00658 }
00659 
00660 
00661 void Translator::dumpQueryResult(QueryResult qres)
00662 {
00663   if(d_translate && d_em->getOutputLang() == SMTLIB_LANG) {
00664     *d_osdump << "  :status ";
00665     switch (qres) {
00666       case UNSATISFIABLE:
00667         *d_osdump << "unsat" << endl;
00668         break;
00669       case SATISFIABLE:
00670         *d_osdump << "sat" << endl;
00671         break;
00672       default:
00673         *d_osdump << "unknown" << endl;
00674         break;
00675     }
00676   }
00677 }
00678 
00679 
00680 Expr Translator::processType(const Expr& e)
00681 {
00682   switch (e.getKind()) {
00683     case INT:
00684       d_intUsed = true;
00685       break;
00686     case REAL:
00687       if (d_real2int) {
00688         d_intUsed = true;
00689         return d_theoryArith->intType().getExpr();
00690       }
00691       else {
00692         d_realUsed = true;
00693       }
00694       break;
00695     case SUBRANGE:
00696       d_unknown = true;
00697       break;
00698     default:
00699       break;
00700   }
00701   d_theoryCore->theoryOf(e)->setUsed();
00702   if (e.arity() == 0) return e;
00703   bool changed = false;
00704   vector<Expr> vec;
00705   for (int i = 0; i < e.arity(); ++i) {
00706     vec.push_back(processType(e[i]));
00707     if (vec.back() != e[i]) changed = true;
00708   }
00709   if (changed)
00710     return Expr(e.getOp(), vec);
00711   return e;
00712 }
00713 
00714 
00715 void Translator::finish()
00716 {
00717   if (d_translate && d_em->getOutputLang() == SMTLIB_LANG) {
00718 
00719     // Print the rest of the preamble for smt-lib benchmarks
00720 
00721     // Get status from expResult flag
00722     *d_osdump << "  :status ";
00723     if (d_expResult == "invalid" ||
00724         d_expResult == "satisfiable")
00725       *d_osdump << "sat";
00726     else if (d_expResult == "valid" ||
00727              d_expResult == "unsatisfiable")
00728       *d_osdump << "unsat";
00729     else *d_osdump << "unknown";
00730     *d_osdump << endl;
00731 
00732     // difficulty
00733     *d_osdump << "  :difficulty { unknown }" << endl;
00734 
00735     // category
00736     *d_osdump << "  :category { ";
00737     *d_osdump << d_category << " }" << endl;
00738 
00739     // Compute logic for smt-lib
00740     bool qf_uf = false;
00741     {
00742       {
00743         ExprMap<Expr> cache;
00744         // Step 1: preprocess asserts, queries, and types
00745         vector<Expr>::iterator i = d_dumpExprs.begin(), iend = d_dumpExprs.end();
00746         for (; i != iend; ++i) {
00747           Expr e = *i;
00748           switch (e.getKind()) {
00749             case ASSERT: {
00750               Expr e2 = preprocess(e[0], cache);
00751               if (e[0] == e2) break;
00752               e2.getType();
00753               *i = Expr(ASSERT, e2);
00754               break;
00755             }
00756             case QUERY: {
00757               Expr e2 = preprocess(e[0].negate(), cache);
00758               if (e[0].negate() == e2) break;
00759               e2.getType();
00760               *i = Expr(QUERY, e2.negate());
00761               break;
00762             }
00763             case CONST: {
00764               DebugAssert(e.arity() == 2, "Expected CONST with arity 2");
00765               Expr e2 = processType(e[1]);
00766               if (e[1] == e2) break;
00767               *i = Expr(CONST, e[0], e2);
00768               break;
00769             }
00770             default:
00771               break;
00772           }
00773         }
00774       }
00775 
00776       if (d_zeroVar) {
00777         d_dumpExprs.insert(d_dumpExprs.begin(),
00778                            Expr(CONST, Expr(ID, d_em->newStringExpr("cvc3Zero")),
00779                                 processType(d_zeroVar->getType().getExpr())));
00780       }
00781 
00782       // Step 2: If both int and real are used, try to separate them
00783       if (!d_unknown && d_intUsed && d_realUsed) {
00784         ExprMap<Expr> cache;
00785         vector<Expr>::iterator i = d_dumpExprs.begin(), iend = d_dumpExprs.end();
00786         for (; i != iend; ++i) {
00787           Expr e = *i;
00788           switch (e.getKind()) {
00789             case ASSERT: {
00790               Expr e2 = preprocess2(e[0], cache);
00791               e2.getType();
00792               *i = Expr(ASSERT, e2);
00793               break;
00794             }
00795             case QUERY: {
00796               Expr e2 = preprocess2(e[0].negate(), cache);
00797               e2.getType();
00798               *i = Expr(QUERY, e2.negate());
00799               break;
00800             }
00801             default:
00802               break;
00803           }
00804         }
00805       }
00806       d_arithUsed = d_realUsed || d_intUsed || d_intConstUsed || (d_langUsed != NOT_USED);
00807 
00808       // Step 3: Go through the cases and figure out the right logic
00809       *d_osdump << "  :logic ";
00810       if (d_unknown ||
00811           d_theoryRecords->theoryUsed() ||
00812           d_theorySimulate->theoryUsed() ||
00813           d_theoryDatatype->theoryUsed()) {
00814         *d_osdump << "unknown";
00815       }
00816       else {
00817         if ((d_ax && (d_arithUsed ||
00818                       d_theoryBitvector->theoryUsed() ||
00819                       d_theoryUF->theoryUsed())) ||
00820             (d_intIntArray && d_realUsed) ||
00821             (d_arithUsed && d_theoryBitvector->theoryUsed())) {
00822           *d_osdump << "unknown";
00823         }
00824         else {
00825           bool QF = false;
00826           bool A = false;
00827           bool UF = false;
00828 
00829           if (!d_theoryQuant->theoryUsed()) {
00830             QF = true;
00831             *d_osdump << "QF_";
00832           }
00833 
00834           if (d_theoryArray->theoryUsed() && !d_convertArray) {
00835             A = true;
00836             *d_osdump << "A";
00837           }
00838 
00839           // Promote undefined subset logics
00840           else if (!QF && !d_theoryBitvector->theoryUsed()) {
00841             A = true;
00842             *d_osdump << "A";
00843           }
00844 
00845           if (d_theoryUF->theoryUsed() ||
00846               (d_theoryArray->theoryUsed() && d_convertArray)) {
00847             UF = true;
00848             *d_osdump << "UF";
00849           }
00850 
00851           // Promote undefined subset logics
00852           else if (!QF &&
00853                    !d_theoryBitvector->theoryUsed()) {
00854             UF = true;
00855             *d_osdump << "UF";
00856           }
00857 
00858           if (d_arithUsed) {
00859             if (d_intUsed && d_realUsed) {
00860               if (d_langUsed < NONLINEAR) {
00861                 *d_osdump << "LIRA";
00862               }
00863               else *d_osdump << "NIRA";
00864             }
00865             else if (d_realUsed) {
00866               if (d_langUsed <= DIFF_ONLY) {
00867 
00868                 // Promote undefined subset logics
00869                 if (!QF) {
00870                   *d_osdump << "LIRA";
00871                 } else
00872 
00873                   *d_osdump << "RDL";
00874               }
00875               else if (d_langUsed <= LINEAR) {
00876 
00877                 // Promote undefined subset logics
00878                 if (!QF) {
00879                   *d_osdump << "LIRA";
00880                 } else
00881 
00882                   *d_osdump << "LRA";
00883               }
00884               else {
00885 
00886                 // Promote undefined subset logics
00887                 if (!QF) {
00888                   *d_osdump << "NIRA";
00889                 } else
00890 
00891                   *d_osdump << "NRA";
00892               }
00893             }
00894             else {
00895               if (QF && !A && UF && d_langUsed <= LINEAR) {
00896                 if (!d_realUsed && d_langUsed <= LINEAR && d_UFIDL_ok) {
00897                   *d_osdump << "IDL";
00898                 }
00899                 else {
00900                   *d_osdump << "LIA";
00901                 }
00902               }
00903               else if (d_langUsed <= DIFF_ONLY) {
00904 
00905                 // Promote undefined subset logics
00906                 if (!QF) {
00907                   *d_osdump << "LIA";
00908                 }
00909                 else if (A) {
00910                   if (!UF) {
00911                     UF = true;
00912                     *d_osdump << "UF";
00913                   }
00914                   *d_osdump << "LIA";                  
00915                 } else
00916 
00917                   *d_osdump << "IDL";
00918               }
00919               else if (d_langUsed <= LINEAR) {
00920 
00921                 // Promote undefined subset logics
00922                 if (QF && A && !UF) {
00923                   UF = true;
00924                   *d_osdump << "UF";
00925                 }
00926 
00927                 if (QF && !A && (!d_realUsed && d_langUsed <= LINEAR && d_UFIDL_ok)) {
00928                   *d_osdump << "UFIDL";
00929                 }
00930                 else {
00931                   *d_osdump << "LIA";
00932                 }
00933               }
00934               else {
00935 
00936                 // Promote undefined subset logics
00937                 if (!QF) {
00938                   *d_osdump << "NIRA";
00939                 } else
00940                 
00941                   *d_osdump << "NIA";
00942               }
00943             }
00944           }
00945           else if (d_theoryBitvector->theoryUsed()) {
00946 
00947             // Promote undefined subset logics
00948             if (A && QF && !UF) {
00949               UF = true;
00950               *d_osdump << "UF";
00951             }
00952 
00953             *d_osdump << "BV";//[" << d_theoryBitvector->getMaxSize() << "]";
00954           }
00955           else {
00956 
00957             if (d_ax) {
00958               *d_osdump << "X";
00959             }
00960 
00961             // Promote undefined subset logics
00962             else if (!QF || (A && UF)) {
00963               *d_osdump << "LIA";
00964             } else {
00965             
00966               // Default logic
00967               if (!A && !UF) {
00968                 UF = true;
00969                 *d_osdump << "UF";
00970               }
00971               qf_uf = QF && UF && (!A);
00972             }
00973           }
00974         }
00975       }
00976     }
00977     *d_osdump << endl;
00978 
00979     // Dump the actual expressions
00980 
00981     vector<Expr>::const_iterator i = d_dumpExprs.begin(), iend = d_dumpExprs.end();
00982     vector<Expr> assumps;
00983     for (; i != iend; ++i) {
00984       Expr e = *i;
00985       switch (e.getKind()) {
00986         case ASSERT: {
00987           if (d_combineAssump) {
00988             assumps.push_back(e[0]);
00989           }
00990           else {
00991             *d_osdump << "  :assumption" << endl;
00992             *d_osdump << e[0] << endl;
00993           }
00994           break;
00995         }
00996         case QUERY: {
00997           *d_osdump << "  :formula" << endl;
00998           if (!assumps.empty()) {
00999             assumps.push_back(e[0].negate());
01000             e = Expr(AND, assumps);
01001             *d_osdump << e << endl;
01002           }
01003           else {
01004             *d_osdump << e[0].negate() << endl;
01005           }
01006           break;
01007         }
01008         default:
01009           if (qf_uf && e.getKind() == TYPE && e[0].getKind() == RAW_LIST &&
01010               e[0][0].getKind() == ID && e[0][0][0].getKind() == STRING_EXPR &&
01011               e[0][0][0].getString() == "U")
01012             break;
01013           *d_osdump << e << endl;
01014           break;
01015       }
01016     }
01017     *d_osdump << ")" << endl;
01018   }
01019 
01020   if (d_dumpFileOpen) d_osdumpFile.close();
01021   if (d_zeroVar) delete d_zeroVar;
01022 }
01023 
01024 
01025 const string Translator::fixConstName(const string& s)
01026 {
01027   if (d_em->getOutputLang() == SMTLIB_LANG) {
01028     if (s[0] == '_') {
01029       return "smt"+s;
01030     }
01031   }
01032   return s;
01033 }
01034 
01035 
01036 bool Translator::printArrayExpr(ExprStream& os, const Expr& e)
01037 {
01038   if (e.getKind() == ARRAY) {
01039     if (d_convertArray) {
01040       os << Expr(ARROW, e[0], e[1]);
01041       return true;
01042     }
01043     if (d_em->getOutputLang() != SMTLIB_LANG) return false;
01044     if (e[0].getKind() == TYPEDECL) {
01045       DebugAssert(e[0].arity() == 1, "expected arity 1");
01046       if (e[0][0].getString() == "Index") {
01047         if (e[1].getKind() == TYPEDECL) {
01048           DebugAssert(e[1].arity() == 1, "expected arity 1");
01049           if (e[1][0].getString() == "Element") {
01050             d_ax = true;
01051             os << "Array";
01052             return true;
01053           }
01054         }
01055       }
01056     }
01057     else if (isInt(Type(e[0]))) {
01058       if (isInt(Type(e[1]))) {
01059         d_intIntArray = true;
01060         os << "Array";
01061         return true;
01062       }
01063       else if (isReal(Type(e[1]))) {
01064         d_intRealArray = true;
01065         os << "Array1";
01066         return true;
01067       }
01068       else if (isArray(Type(e[1])) &&
01069                isInt(Type(e[1][0])) &&
01070                isReal(Type(e[1][1]))) {
01071         d_intIntRealArray = true;
01072         os << "Array2";
01073         return true;
01074       }
01075     }
01076     else if (e[0].getKind() == BITVECTOR &&
01077              e[1].getKind() == BITVECTOR) {
01078       os << "Array[";
01079       os << d_theoryBitvector->getBitvectorTypeParam(Type(e[0]));
01080       os << ":";
01081       os << d_theoryBitvector->getBitvectorTypeParam(Type(e[1]));
01082       os << "]";
01083       return true;
01084     }
01085     os << "Array";
01086     d_unknown = true;
01087     return true;
01088   }
01089 
01090   switch (e.getKind()) {
01091     case READ:
01092       if (d_convertArray) {
01093         if (e[0].getKind() == UCONST) {
01094           os << Expr(d_em->newSymbolExpr(e[0].getName(), UFUNC).mkOp(), e[1]);
01095           return true;
01096         }
01097         else if (e[0].getKind() == WRITE) {
01098           throw Exception("READ of WRITE not implemented yet for convertArray");
01099         }
01100         else {
01101           throw Exception("Unexpected case for convertArray");
01102         }
01103       }
01104       break;
01105     case WRITE:
01106       if (d_convertArray) {
01107         throw Exception("WRITE expression encountered while attempting "
01108                         "to convert arrays to uninterpreted functions");
01109       }
01110       break;
01111     case ARRAY_LITERAL:
01112       if (d_convertArray) {
01113         throw Exception("ARRAY_LITERAL expression encountered while attempting"
01114                         " to convert arrays to uninterpreted functions");
01115       }
01116       break;
01117     default:
01118       throw Exception("Unexpected case in printArrayExpr");
01119       break;
01120   }
01121   return false;
01122 }
01123 
01124 
01125 Expr Translator::zeroVar()
01126 {
01127   if (!d_zeroVar) {
01128     d_zeroVar = new Expr();
01129     if (d_convertToDiff == "int") {
01130       *d_zeroVar = d_theoryCore->newVar("cvc3Zero", d_theoryArith->intType().getExpr());
01131     }
01132     else if (d_convertToDiff == "real") {
01133       *d_zeroVar = d_theoryCore->newVar("cvc3Zero", d_theoryArith->realType().getExpr());
01134     }
01135   }
01136   return *d_zeroVar;
01137 }

Generated on Tue Jul 3 14:33:42 2007 for CVC3 by  doxygen 1.5.1