CVC3

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 <cctype>
00024 
00025 #include "translator.h"
00026 #include "expr.h"
00027 #include "theory_core.h"
00028 #include "theory_uf.h"
00029 #include "theory_arith.h"
00030 #include "theory_bitvector.h"
00031 #include "theory_array.h"
00032 #include "theory_quant.h"
00033 #include "theory_records.h"
00034 #include "theory_simulate.h"
00035 #include "theory_datatype.h"
00036 #include "theory_datatype_lazy.h"
00037 #include "smtlib_exception.h"
00038 #include "command_line_flags.h"
00039 
00040 
00041 using namespace std;
00042 using namespace CVC3;
00043 
00044 
00045 string Translator::fileToSMTLIBIdentifier(const string& filename)
00046 {
00047   string tmpName;
00048   string::size_type pos = filename.rfind("/");
00049   if (pos == string::npos) {
00050     tmpName = filename;
00051   }
00052   else {
00053     tmpName = filename.substr(pos+1);
00054   }
00055   char c = tmpName[0];
00056   string res;
00057   if ((c < 'A' || c > 'Z') && (c < 'a' || c > 'z')) {
00058     res = "B_";
00059   }
00060   for (unsigned i = 0; i < tmpName.length(); ++i) {
00061     c = tmpName[i];
00062     if ((c < 'A' || c > 'Z') && (c < 'a' || c > 'z') &&
00063         (c < '0' || c > '9') && (c != '.' && c != '_')) {
00064       c = '_';
00065     }
00066     res += c;
00067   }
00068   return res;
00069 }
00070 
00071 
00072 Expr Translator::preprocessRec(const Expr& e, ExprMap<Expr>& cache)
00073 {
00074   ExprMap<Expr>::iterator i(cache.find(e));
00075   if(i != cache.end()) {
00076     return (*i).second;
00077   }
00078 
00079   if (d_theoryCore->getFlags()["liftITE"].getBool() &&
00080       e.isPropAtom() && e.containsTermITE()) {
00081     Theorem thm = d_theoryCore->getCommonRules()->liftOneITE(e);
00082     return preprocessRec(thm.getRHS(), cache);
00083   }
00084 
00085   if (e.isClosure()) {
00086     Expr newBody = preprocessRec(e.getBody(), cache);
00087     Expr e2(e);
00088     if (newBody != e.getBody()) {
00089       e2 = d_em->newClosureExpr(e.getKind(), e.getVars(), newBody);
00090     }
00091     d_theoryCore->theoryOf(e2)->setUsed();
00092     cache[e] = e2;
00093     return e2;
00094   }
00095 
00096   Expr e2(e);
00097   vector<Expr> children;
00098   bool diff = false;
00099 
00100   for(int k = 0; k < e.arity(); ++k) {
00101     // Recursively preprocess the kids
00102     Expr child = preprocessRec(e[k], cache);
00103     if (child != e[k]) diff = true;
00104     children.push_back(child);
00105   }
00106   if (diff) {
00107     e2 = Expr(e.getOp(), children);
00108   }
00109 
00110   Rational r;
00111   switch (e2.getKind()) {
00112     case RATIONAL_EXPR:
00113       if (d_convertToBV) {
00114         Rational r = e2.getRational();
00115         if (!r.isInteger()) {
00116           FatalAssert(false, "Cannot convert non-integer constant to BV");
00117         }
00118         Rational limit = pow(d_convertToBV-1, (Rational)2);
00119         if (r >= limit) {
00120           FatalAssert(false, "Cannot convert to BV: integer too big");
00121         }
00122         else if (r < -limit) {
00123           FatalAssert(false, "Cannot convert to BV: integer too small");
00124         }
00125         e2 = d_theoryBitvector->signed_newBVConstExpr(r, d_convertToBV);
00126         break;
00127       }
00128 
00129     case READ:
00130       if (!d_unknown && d_theoryCore->getFlags()["convert2array"].getBool()) {
00131         if (e2[1].getKind() != UCONST) break;
00132         map<string, Type>::iterator i = d_arrayConvertMap->find(e2[1].getName());
00133         if (i == d_arrayConvertMap->end()) {
00134           (*d_arrayConvertMap)[e2[1].getName()] = *d_indexType;
00135         }
00136         else {
00137           if ((*i).second != (*d_indexType)) {
00138             d_unknown = true;
00139           }
00140         }
00141       }
00142       break;
00143 
00144     case WRITE:
00145       if (!d_unknown && d_theoryCore->getFlags()["convert2array"].getBool()) {
00146         map<string, Type>::iterator i;
00147         if (e2[1].getKind() == UCONST) {
00148           i = d_arrayConvertMap->find(e2[1].getName());
00149           if (i == d_arrayConvertMap->end()) {
00150             (*d_arrayConvertMap)[e2[1].getName()] = *d_indexType;
00151           }
00152           else {
00153             if ((*i).second != (*d_indexType)) {
00154               d_unknown = true;
00155               break;
00156             }
00157           }
00158         }
00159         if (e2[2].getKind() != UCONST) break;
00160         i = d_arrayConvertMap->find(e2[2].getName());
00161         if (i == d_arrayConvertMap->end()) {
00162           (*d_arrayConvertMap)[e2[2].getName()] = *d_elementType;
00163         }
00164         else {
00165           if ((*i).second != (*d_elementType)) {
00166             d_unknown = true;
00167           }
00168         }
00169       }
00170       break;
00171 
00172     case APPLY:
00173       // Expand lambda applications
00174       if (e2.getOpKind() == LAMBDA) {
00175         Expr lambda(e2.getOpExpr());
00176         Expr body(lambda.getBody());
00177         const vector<Expr>& vars = lambda.getVars();
00178         FatalAssert(vars.size() == (size_t)e2.arity(),
00179                     "wrong number of arguments applied to lambda\n");
00180         body = body.substExpr(vars, e2.getKids());
00181         e2 = preprocessRec(body, cache);
00182       }
00183       break;
00184 
00185     case EQ:
00186       if (d_theoryArith->getBaseType(e2[0]) != d_theoryArith->realType())
00187         break;
00188       if (d_theoryCore->getFlags()["convert2array"].getBool() &&
00189           ((e2[0].getKind() == UCONST && d_arrayConvertMap->find(e2[0].getName()) == d_arrayConvertMap->end()) ||
00190           (e2[1].getKind() == UCONST && d_arrayConvertMap->find(e2[1].getName()) == d_arrayConvertMap->end()))) {
00191         d_equalities.push_back(e2);
00192       }
00193       goto arith_rewrites;
00194 
00195     case UMINUS:
00196       if (d_convertToBV) {
00197         e2 = Expr(BVUMINUS, e2[0]);
00198         break;
00199       }
00200       if (d_theoryArith->isSyntacticRational(e2, r)) {
00201         e2 = preprocessRec(d_em->newRatExpr(r), cache);
00202         break;
00203       }
00204       goto arith_rewrites;
00205 
00206     case DIVIDE:
00207       if (d_convertToBV) {
00208         FatalAssert(false, "Conversion of DIVIDE to BV not implemented yet");
00209         break;
00210       }
00211       if (d_theoryArith->isSyntacticRational(e2, r)) {
00212         e2 = preprocessRec(d_em->newRatExpr(r), cache);
00213         break;
00214       }
00215       else if (d_convertArith && e2[1].isRational()) {
00216         r = e2[1].getRational();
00217         if (r != 0) {
00218           e2 = d_em->newRatExpr(1/r) * e2[0];
00219           e2 = preprocessRec(e2, cache);
00220           break;
00221         }
00222       }
00223       goto arith_rewrites;
00224 
00225     case MINUS:
00226       if (d_convertToBV) {
00227         e2 = Expr(BVSUB, e2[0], e2[1]);
00228         break;
00229       }
00230       if (d_convertArith) {
00231         if (e2[0].isRational() && e2[1].isRational()) {
00232           e2 = d_em->newRatExpr(e2[0].getRational() - e2[1].getRational());
00233           break;
00234         }
00235       }
00236       goto arith_rewrites;
00237 
00238     case PLUS:
00239       if (d_convertToBV) {
00240         e2 = Expr(Expr(BVPLUS, d_em->newRatExpr(d_convertToBV)).mkOp(), e2.getKids());
00241         break;
00242       }
00243       if (d_convertArith) {
00244         // Flatten and combine constants
00245         vector<Expr> terms;
00246         bool changed = false;
00247         int numConst = 0;
00248         r = 0;
00249         Expr::iterator i = e2.begin(), iend = e2.end();
00250         for(; i!=iend; ++i) {
00251           if ((*i).getKind() == PLUS) {
00252             changed = true;
00253             Expr::iterator i2 = (*i).begin(), i2end = (*i).end();
00254             for (; i2 != i2end; ++i2) {
00255               if ((*i2).isRational()) {
00256                 r += (*i2).getRational();
00257                 numConst++;
00258               }
00259               else terms.push_back(*i2);
00260             }
00261           }
00262           else {
00263             if ((*i).isRational()) {
00264               r += (*i).getRational();
00265               numConst++;
00266               if (numConst > 1) changed = true;
00267             }
00268             else terms.push_back(*i);
00269           }
00270         }
00271         if (terms.size() == 0) {
00272           e2 = preprocessRec(d_em->newRatExpr(r), cache);
00273           break;
00274         }
00275         else if (terms.size() == 1) {
00276           if (r == 0) {
00277             e2 = terms[0];
00278             break;
00279           }
00280           else if (r < 0) {
00281             e2 = preprocessRec(Expr(MINUS, terms[0], d_em->newRatExpr(-r)), cache);
00282             break;
00283           }
00284         }
00285         if (changed) {
00286           if (r != 0) terms.push_back(d_em->newRatExpr(r));
00287           e2 = preprocessRec(Expr(PLUS, terms), cache);
00288           break;
00289         }
00290       }
00291       goto arith_rewrites;
00292 
00293     case MULT:
00294       if (d_convertToBV) {
00295         e2 = Expr(Expr(BVMULT, d_em->newRatExpr(d_convertToBV)).mkOp(), e2.getKids());
00296         break;
00297       }
00298       if (d_convertArith) {
00299         // Flatten and combine constants
00300         vector<Expr> terms;
00301         bool changed = false;
00302         int numConst = 0;
00303         r = 1;
00304         Expr::iterator i = e2.begin(), iend = e2.end();
00305         for(; i!=iend; ++i) {
00306           if ((*i).getKind() == MULT) {
00307             changed = true;
00308             Expr::iterator i2 = (*i).begin(), i2end = (*i).end();
00309             for (; i2 != i2end; ++i2) {
00310               if ((*i2).isRational()) {
00311                 r *= (*i2).getRational();
00312                 numConst++;
00313               }
00314               else terms.push_back(*i2);
00315             }
00316           }
00317           else {
00318             if ((*i).isRational()) {
00319               r *= (*i).getRational();
00320               numConst++;
00321               if (numConst > 1) changed = true;
00322             }
00323             else terms.push_back(*i);
00324           }
00325         }
00326         if (r == 0) {
00327           e2 = preprocessRec(d_em->newRatExpr(0), cache);
00328           break;
00329         }
00330         else if (terms.size() == 0) {
00331           e2 = preprocessRec(d_em->newRatExpr(r), cache);
00332           break;
00333         }
00334         else if (terms.size() == 1) {
00335           if (r == 1) {
00336             e2 = terms[0];
00337             break;
00338           }
00339         }
00340         if (changed) {
00341           if (r != 1) terms.push_back(d_em->newRatExpr(r));
00342           e2 = preprocessRec(Expr(MULT, terms), cache);
00343           break;
00344         }
00345       }
00346       goto arith_rewrites;
00347 
00348     case POW:
00349       if (d_convertToBV) {
00350         FatalAssert(false, "Conversion of POW to BV not implemented");
00351         break;
00352       }
00353       if (d_convertArith && e2[0].isRational()) {
00354         r = e2[0].getRational();
00355         if (r.isInteger() && r.getNumerator() == 2) {
00356           e2 = preprocessRec(e2[1] * e2[1], cache);
00357           break;
00358         }
00359       }
00360       // fall through
00361 
00362     case LT:
00363       if (d_convertToBV) {
00364         e2 = Expr(BVSLT, e2[0], e2[1]);
00365         break;
00366       }
00367 
00368     case GT:
00369       if (d_convertToBV) {
00370         e2 = Expr(BVSLT, e2[1], e2[0]);
00371         break;
00372       }
00373 
00374     case LE:
00375       if (d_convertToBV) {
00376         e2 = Expr(BVSLE, e2[0], e2[1]);
00377         break;
00378       }
00379 
00380     case GE:
00381       if (d_convertToBV) {
00382         e2 = Expr(BVSLE, e2[1], e2[0]);
00383         break;
00384       }
00385       
00386 
00387     case INTDIV:
00388     case MOD:
00389 
00390   arith_rewrites:
00391       if (d_iteLiftArith) {
00392         diff = false;
00393         children.clear();
00394         vector<Expr> children2;
00395         Expr cond;
00396         for (int k = 0; k < e2.arity(); ++k) {
00397           if (e2[k].getKind() == ITE && !diff) {
00398             diff = true;
00399             cond = e2[k][0];
00400             children.push_back(e2[k][1]);
00401             children2.push_back(e2[k][2]);
00402           }
00403           else {
00404             children.push_back(e2[k]);
00405             children2.push_back(e2[k]);
00406           }
00407         }
00408         if (diff) {
00409           Expr thenpart = Expr(e2.getOp(), children);
00410           Expr elsepart = Expr(e2.getOp(), children2);
00411           e2 = cond.iteExpr(thenpart, elsepart);
00412           e2 = preprocessRec(e2, cache);
00413           break;
00414         }
00415       }
00416 
00417       if (d_convertToDiff != "" && d_theoryArith->isAtomicArithFormula(e2)) {
00418         Expr e3 = d_theoryArith->rewriteToDiff(e2);
00419         if (e2 != e3) {
00420           DebugAssert(e3 == d_theoryArith->rewriteToDiff(e3), "Expected idempotent rewrite");
00421           e2 = preprocessRec(e3, cache);
00422         }
00423         break;
00424       }
00425 
00426       break;
00427     default:
00428       if (d_convertToBV && isInt(e2.getType())) {
00429         FatalAssert(e2.isVar(), "Cannot convert non-variables yet");
00430         e2 = d_theoryCore->newVar(e2.getName()+"_bv", d_theoryBitvector->newBitvectorType(d_convertToBV));
00431       }
00432 
00433       break;
00434   }
00435 
00436   // Figure out language
00437   switch (e2.getKind()) {
00438     case RATIONAL_EXPR:
00439       r = e2.getRational();
00440       if (r.isInteger()) {
00441         d_intConstUsed = true;
00442       }
00443       else {
00444         d_realUsed = true;
00445       }
00446       if (d_langUsed == NOT_USED) d_langUsed = TERMS_ONLY;
00447       break;
00448     case IS_INTEGER:
00449       d_realUsed = true;
00450       d_intUsed = true;
00451       break;
00452     case PLUS: {
00453       if (e2.arity() == 2) {
00454         int nonconst = 0, isconst = 0;
00455         Expr::iterator i = e2.begin(), iend = e2.end();
00456         for(; i!=iend; ++i) {
00457           if ((*i).isRational()) {
00458             if ((*i).getRational() <= 0) {
00459               d_UFIDL_ok = false;
00460               break;
00461             }
00462             else ++isconst;
00463           }
00464           else ++nonconst;
00465         }
00466         if (nonconst > 1 || isconst > 1)
00467           d_UFIDL_ok = false;
00468       }
00469       else d_UFIDL_ok = false;
00470       if (d_langUsed == NOT_USED) d_langUsed = TERMS_ONLY;
00471       break;
00472     }
00473     case MINUS:
00474       if (!e2[1].isRational() || e2[1].getRational() <= 0) {
00475         d_UFIDL_ok = false;
00476       }
00477       if (d_langUsed == NOT_USED) d_langUsed = TERMS_ONLY;
00478       break;
00479     case UMINUS:
00480       d_UFIDL_ok = false;
00481       if (d_langUsed == NOT_USED) d_langUsed = TERMS_ONLY;
00482       break;
00483     case MULT: {
00484       d_UFIDL_ok = false;
00485       if (d_langUsed == NONLINEAR) break;
00486       d_langUsed = LINEAR;
00487       bool nonconst = false;
00488       for (int i=0; i!=e2.arity(); ++i) {
00489         if (e2[i].isRational()) continue;
00490         if (nonconst) {
00491           d_langUsed = NONLINEAR;
00492           break;
00493         }
00494         nonconst = true;
00495       }
00496       break;
00497     }
00498     case POW:
00499     case DIVIDE:
00500       d_unknown = true;
00501       break;
00502 
00503     case EQ:
00504       if (d_theoryArith->getBaseType(e2[0]) != d_theoryArith->realType() ||
00505           (e2[0].getType() == d_theoryArith->intType() && d_theoryCore->getFlags()["convert2array"].getBool()))
00506         break;
00507     case LT:
00508     case GT:
00509     case LE:
00510     case GE:
00511       if (d_langUsed >= LINEAR) break;
00512       if (!d_theoryArith->isAtomicArithFormula(e2)) {
00513         d_langUsed = LINEAR;
00514         break;
00515       }
00516       if (e2[0].getKind() == MINUS &&
00517           d_theoryArith->isLeaf(e2[0][0]) &&
00518           d_theoryArith->isLeaf(e2[0][1]) &&
00519           e2[1].isRational()) {
00520         d_langUsed = DIFF_ONLY;
00521         break;
00522       }
00523       if (d_theoryArith->isLeaf(e2[0]) &&
00524           d_theoryArith->isLeaf(e2[1])) {
00525         d_langUsed = DIFF_ONLY;
00526         break;
00527       }
00528       d_langUsed = LINEAR;
00529       break;
00530     default:
00531       break;
00532   }
00533 
00534   switch (e2.getKind()) {
00535     case EQ:
00536     case NOT:
00537       break;
00538     case UCONST:
00539       if (e2.arity() == 0) break;
00540     default:
00541       d_theoryCore->theoryOf(e2)->setUsed();
00542   }
00543 
00544   cache[e] = e2;
00545   return e2;
00546 }
00547 
00548 
00549 Expr Translator::preprocess(const Expr& e, ExprMap<Expr>& cache)
00550 {
00551   Expr result;
00552   try {
00553     result = preprocessRec(e, cache);
00554   } catch (SmtlibException& ex) {
00555     cerr << "Error while processing the formula:\n"
00556          << e.toString() << endl;
00557     throw ex;
00558   }
00559   return result;
00560 }
00561 
00562 
00563 Expr Translator::preprocess2Rec(const Expr& e, ExprMap<Expr>& cache, Type desiredType)
00564 {
00565   TRACE("smtlib2-linear", "preprocess2Rec: ", e, "");
00566   ExprMap<Expr>::iterator i(cache.find(e));
00567   if(i != cache.end()) {
00568     if ((desiredType.isNull() &&
00569          (*i).second.getType() != d_theoryArith->realType()) ||
00570         (*i).second.getType() == desiredType) {
00571       return (*i).second;
00572     }
00573   }
00574 
00575   if (e.isClosure()) {
00576     Expr newBody = preprocess2Rec(e.getBody(), cache, Type());
00577     Expr e2(e);
00578     if (newBody != e.getBody()) {
00579       e2 = d_em->newClosureExpr(e.getKind(), e.getVars(), newBody);
00580     }
00581     cache[e] = e2;
00582     return e2;
00583   }
00584 
00585   bool forceReal = false;
00586   if (desiredType == d_theoryArith->intType() &&
00587       e.getType() != d_theoryArith->intType()) {
00588     d_unknown = true;
00589 //     throw SmtlibException("Unable to separate int and real "+
00590 //                           e.getType().getExpr().toString()+
00591 //                           "\n\nwhile processing the term:\n"+
00592 //                           e.toString(PRESENTATION_LANG));
00593   }
00594 
00595   // Try to force type-compliance
00596   switch (e.getKind()) {
00597     case EQ:
00598     case LT:
00599     case GT:
00600     case LE:
00601     case GE:
00602       if (e[0].getType() != e[1].getType()) {
00603         if (e[0].getType() != d_theoryArith->intType() &&
00604             e[1].getType() != d_theoryArith->intType()) {
00605           d_unknown = true;
00606           throw SmtlibException("Expected each side to be REAL or INT, but we got lhs: "+
00607                                 e[0].getType().getExpr().toString()+" and rhs: "+
00608                                 e[1].getType().getExpr().toString()+
00609                                 "\n\nwhile processing the term:\n"+
00610                                 e.toString());
00611         }
00612         forceReal = true;
00613         break;
00614       case ITE:
00615       case UMINUS:
00616       case PLUS:
00617       case MINUS:
00618       case MULT:
00619         if (desiredType == d_theoryArith->realType())
00620           forceReal = true;
00621         break;
00622       case DIVIDE:
00623         forceReal = true;
00624         break;
00625       default:
00626         break;
00627     }
00628   }
00629 
00630   Expr e2(e);
00631   vector<Expr> children;
00632   bool diff = false;
00633 
00634   Type funType;
00635   if (e.isApply()) {
00636     funType = e.getOpExpr().getType();
00637     if (funType.getExpr().getKind() == ANY_TYPE) funType = Type();
00638   }
00639   else if (e.getKind() == WRITE) {
00640     // an array store is like a function ARRAY -> INDEX -> ELEMENT -> ARRAY
00641     vector<Type> kids;
00642     kids.push_back(e.getType());
00643     kids.push_back(e.getType()[0]);
00644     kids.push_back(e.getType()[1]);
00645     funType = Type::funType(kids, e.getType());
00646   }
00647 
00648   for(int k = 0; k < e.arity(); ++k) {
00649     Type t;
00650     if (forceReal && e[k].getType() == d_theoryArith->intType())
00651       t = d_theoryArith->realType();
00652     else if (!funType.isNull()) t = funType[k];
00653     // Recursively preprocess the kids
00654     Expr child = preprocess2Rec(e[k], cache, t);
00655     if (child != e[k]) diff = true;
00656     children.push_back(child);
00657   }
00658   if (diff) {
00659     e2 = Expr(e.getOp(), children);
00660   }
00661   else if (e2.getKind() == RATIONAL_EXPR && d_realUsed && d_intUsed) {
00662     if (e2.getType() == d_theoryArith->realType() ||
00663         (e2.getType() == d_theoryArith->intType() &&
00664          desiredType == d_theoryArith->realType()))
00665       e2 = Expr(REAL_CONST, e2);
00666   }
00667   if (e2.getKind() == MULT) {
00668     // SMT-LIBv2 is strict about where * is permitted in linear logics
00669     if (d_langUsed > NOT_USED && d_langUsed <= LINEAR &&
00670         d_em->getOutputLang() == SMTLIB_V2_LANG) {
00671       Expr e2save = e2;
00672       TRACE("smtlib2-linear", "SMT-LIBv2 linearizing: ", e2save, "");
00673       FatalAssert(e2.arity() > 1, "Unary MULT not permitted here");
00674       // combine constants to form a linear term
00675       Expr trm;// the singular, non-constant term in the MULT
00676       Rational constCoef = 1;// constant coefficient
00677       bool realConst = false;
00678       bool trmFirst = false;
00679       for(int i = 0; i < e2.arity(); ++i) {
00680         Expr x = e2[i];
00681         if(x.getKind() == REAL_CONST) {
00682           x = x[0];
00683           realConst = true;
00684           DebugAssert(x.isRational(), "unexpected REAL_CONST-wrapped kind");
00685         }
00686         if(x.isRational()) {
00687           constCoef *= x.getRational();
00688         } else {
00689           FatalAssert(trm.isNull(), "translating with LINEAR restriction, but found > 1 non-constant under MULT");
00690           trm = x;
00691           trmFirst = (i == 0);
00692         }
00693       }
00694 
00695       // First, do no harm: if it was a binary MULT already in correct shape
00696       // for SMT-LIBv2 linear logics, use it.
00697       if( !( e2.arity() == 2 && !trm.isNull() &&
00698              (trm.isApply() || trm.getKind() == READ || trm.isVar()) ) ) {
00699         // Otherwise, there are several cases, enumerated below.
00700 
00701         Expr coef = d_em->newRatExpr(constCoef);
00702         if(realConst) {
00703           // if any part of the coefficient was wrapped with REAL_CONST to
00704           // force printing as a real (e.g. "1.0"), then wrap the combined
00705           // coefficient
00706           coef = Expr(REAL_CONST, coef);
00707         }
00708 
00709         if(trm.isNull()) {
00710           // Case 1: entirely constant; the mult goes away
00711           TRACE("smtlib2-linear", "(1) constant", "", "");
00712           e2 = coef;
00713         } else if(constCoef == 1) {
00714           // Case 2: unit coefficient; the mult goes away
00715           TRACE("smtlib2-linear", "(2) unit coefficient: ", trm, "");
00716           e2 = trm;
00717         } else if(trm.getKind() == PLUS || trm.getKind() == MINUS) {
00718           // Case 3: have to distribute the MULT over PLUS/MINUS
00719           TRACE("smtlib2-linear", "(3) mult over plus/minus: ", trm, "");
00720           vector<Expr> kids;
00721           for(int i = 0; i < trm.arity(); ++i) {
00722             Expr trmi(MULT, coef, trm[i]);
00723             trmi = preprocess2Rec(trmi, cache, desiredType);
00724             kids.push_back(trmi);
00725           }
00726           e2 = Expr(trm.getKind(), kids);
00727         } else if(trm.getKind() == MULT) {
00728           // Case 4: have to distribute MULT over MULT
00729           TRACE("smtlib2-linear", "(4) mult over mult: ", trm, "");
00730           vector<Expr> kids;
00731           kids.push_back(coef);
00732           for(int i = 0; i < trm.arity(); ++i) {
00733             kids.push_back(trm[i]);
00734           }
00735           e2 = Expr(MULT, kids);
00736           e2 = preprocess2Rec(e2, cache, desiredType);
00737         } else if(trm.getKind() == ITE) {
00738           // Case 5: have to distribute MULT over ITE
00739           TRACE("smtlib2-linear", "(5) mult over ite: ", trm, "");
00740           Expr thn = Expr(MULT, coef, trm[1]);
00741           Expr els = Expr(MULT, coef, trm[2]);
00742           thn = preprocess2Rec(thn, cache, desiredType);
00743           els = preprocess2Rec(els, cache, desiredType);
00744           e2 = Expr(ITE, trm[0], thn, els);
00745         } else {
00746           // Default case: 
00747           TRACE("smtlib2-linear", "(*) coef, trm: ", coef, trm);
00748           // don't change order if not necessary (makes it easier to inspect the translation)
00749           if(trmFirst) {
00750             e2 = Expr(MULT, trm, coef);
00751           } else {
00752             e2 = Expr(MULT, coef, trm);
00753           }
00754           FatalAssert(trm.isVar(), string("translating with LINEAR restriction, but found malformed MULT over term that's not a free constant: ") + e2.toString());
00755         }
00756       } else {
00757         TRACE("smtlib2-linear", "(x) no handling necessary: ", trm, "");
00758       }
00759       TRACE("smtlib2-linear", "SMT-LIBv2 linearized: ", e2save, "");
00760       TRACE("smtlib2-linear", "                into: ", e2, "");
00761     }
00762   }
00763 
00764   if (!desiredType.isNull() && e2.getType() != desiredType) {
00765     if(isInt(e2.getType()) && isReal(desiredType) && !d_intUsed) {
00766       // the implicit cast is ok here
00767     } else {
00768       d_unknown = true;
00769       throw SmtlibException("Type error: expected "+
00770                             desiredType.getExpr().toString()+
00771                             " but instead got "+
00772                             e2.getType().getExpr().toString()+
00773                             "\n\nwhile processing term:\n"+
00774                             e.toString());
00775     }
00776   }
00777 
00778   cache[e] = e2;
00779   return e2;
00780 }
00781 
00782 
00783 Expr Translator::preprocess2(const Expr& e, ExprMap<Expr>& cache)
00784 {
00785   Expr result;
00786   try {
00787     result = preprocess2Rec(e, cache, Type());
00788   } catch (SmtlibException& ex) {
00789     cerr << "Error while processing the formula:\n"
00790          << e.toString() << endl;
00791     throw ex;
00792   }
00793   return result;
00794 }
00795 
00796 
00797 
00798 
00799 bool Translator::containsArray(const Expr& e)
00800 {
00801   if (e.getKind() == ARRAY) return true;
00802   Expr::iterator i = e.begin(), iend=e.end();
00803   for(; i!=iend; ++i) if (containsArray(*i)) return true;
00804   return false;
00805 }
00806 
00807 
00808 Translator::Translator(ExprManager* em,
00809                        const bool& translate,
00810                        const bool& real2int,
00811                        const bool& convertArith,
00812                        const string& convertToDiff,
00813                        bool iteLiftArith,
00814                        const string& expResult,
00815                        const string& category,
00816                        bool convertArray,
00817                        bool combineAssump,
00818                        int convertToBV)
00819   : d_em(em), d_translate(translate),
00820     d_real2int(real2int),
00821     d_convertArith(convertArith),
00822     d_convertToDiff(convertToDiff),
00823     d_iteLiftArith(iteLiftArith),
00824     d_expResult(expResult),
00825     d_category(category),
00826     d_convertArray(convertArray),
00827     d_combineAssump(combineAssump),
00828     d_dump(false), d_dumpFileOpen(false),
00829     d_intIntArray(false), d_intRealArray(false), d_intIntRealArray(false),
00830     d_ax(false), d_unknown(false),
00831     d_realUsed(false), d_intUsed(false), d_intConstUsed(false),
00832     d_langUsed(NOT_USED), d_UFIDL_ok(true), d_arithUsed(false),
00833     d_zeroVar(NULL), d_convertToBV(convertToBV)
00834 {
00835   d_arrayConvertMap = new map<string, Type>;
00836 }
00837 
00838 
00839 Translator::~Translator()
00840 {
00841   delete d_arrayConvertMap;
00842 }
00843 
00844 
00845 bool Translator::start(const string& dumpFile)
00846 {
00847   if (d_translate && (d_em->getOutputLang() == SMTLIB_LANG)) {
00848     d_dump = true;
00849     if (dumpFile == "") {
00850       d_osdump = &cout;
00851     }
00852     else {
00853       d_osdumpFile.open(dumpFile.c_str());
00854       if(!d_osdumpFile)
00855         throw Exception("cannot open a log file: "+dumpFile);
00856       else {
00857         d_dumpFileOpen = true;
00858         d_osdump = &d_osdumpFile;
00859       }
00860     }
00861 
00862     string tmpName;
00863     string::size_type pos = dumpFile.rfind("/");
00864     if (pos == string::npos) {
00865       tmpName = "README";
00866     }
00867     else {
00868       tmpName = dumpFile.substr(0,pos+1) + "README";
00869     }
00870     d_tmpFile.open(tmpName.c_str());
00871 
00872       *d_osdump << "(benchmark " << fileToSMTLIBIdentifier(dumpFile) << endl
00873           << "  :source {" << endl;
00874 
00875       char c;
00876       if (d_tmpFile.is_open()) {
00877         d_tmpFile.get(c);
00878         while (!d_tmpFile.eof()) {
00879           if ( c == '{' || c == '}' ) {
00880             *d_osdump << '\\';
00881           }
00882           *d_osdump << c;
00883           d_tmpFile.get(c);
00884         }
00885       }
00886       else {
00887         *d_osdump << "Source unknown";
00888       }
00889       *d_osdump << endl;
00890 
00891       *d_osdump << "}" << endl;
00892 
00893     d_tmpFile.close();
00894   }
00895   else if (d_translate && d_em->getOutputLang() == SPASS_LANG) {
00896     d_dump = true;
00897     if (dumpFile == "") {
00898       d_osdump = &cout;
00899     }
00900     else {
00901       d_osdumpFile.open(dumpFile.c_str());
00902       if(!d_osdumpFile)
00903         throw Exception("cannot open a log file: "+dumpFile);
00904       else {
00905         d_dumpFileOpen = true;
00906         d_osdump = &d_osdumpFile;
00907       }
00908     }
00909 
00910     *d_osdump << "begin_problem(Unknown). " << endl;
00911     *d_osdump << endl;
00912     *d_osdump << "list_of_descriptions. " << endl;
00913     *d_osdump << "name({* " <<  fileToSMTLIBIdentifier(dumpFile) << " *}). " << endl;
00914     *d_osdump << "author({* CVC2SPASS translator *})." << endl;
00915     //end of SPASS
00916   }
00917   else {
00918     if (dumpFile == "") {
00919       if (d_translate) {
00920         d_osdump = &cout;
00921         d_dump = true;
00922       }
00923     }
00924     else {
00925       d_osdumpFile.open(dumpFile.c_str());
00926       if(!d_osdumpFile)
00927         throw Exception("cannot open a log file: "+dumpFile);
00928       else {
00929         d_dump = true;
00930         d_dumpFileOpen = true;
00931         d_osdump = &d_osdumpFile;
00932       }
00933     }
00934   }
00935   return d_dump;
00936 }
00937 
00938 
00939 void Translator::dump(const Expr& e, bool dumpOnly)
00940 {
00941   DebugAssert(d_dump, "dump called unexpectedly");
00942   if (!dumpOnly || !d_translate) {
00943     if (d_convertArray && e.getKind() == CONST &&
00944         e.arity() == 2) {
00945       if (e[1].getKind() == ARRAY) {
00946         if (containsArray(e[1][0]) ||
00947             containsArray(e[1][1])) {
00948           throw Exception("convertArray failed because of nested arrays in"+
00949                           e[1].toString());
00950         }
00951         Expr funType = Expr(ARROW, e[1][0], e[1][1]);
00952         Expr outExpr = Expr(CONST, e[0], funType);
00953         d_dumpExprs.push_back(outExpr);
00954       }
00955       else if (containsArray(e[1])) {
00956         throw Exception("convertArray failed becauase of use of arrays in"+
00957                         e[1].toString());
00958       }
00959       else {
00960         d_dumpExprs.push_back(e);
00961       }
00962     }
00963     else {
00964       d_dumpExprs.push_back(e);
00965     }
00966   }
00967 }
00968 
00969 
00970 bool Translator::dumpAssertion(const Expr& e)
00971 {
00972   Expr outExpr = Expr(ASSERT, e);
00973   d_dumpExprs.push_back(outExpr);
00974   return d_translate;
00975 }
00976 
00977 
00978 bool Translator::dumpQuery(const Expr& e)
00979 {
00980   Expr outExpr = Expr(QUERY, e);
00981   d_dumpExprs.push_back(outExpr);
00982   return d_translate;
00983 }
00984 
00985 
00986 void Translator::dumpQueryResult(QueryResult qres)
00987 {
00988   if( d_translate && d_em->getOutputLang() == SMTLIB_LANG ) {
00989     *d_osdump << "  :status ";
00990     switch( qres ) {
00991     case UNSATISFIABLE:
00992       *d_osdump << "unsat" << endl;
00993       break;
00994     case SATISFIABLE:
00995       *d_osdump << "sat" << endl;
00996       break;
00997     default:
00998       *d_osdump << "unknown" << endl;
00999       break;
01000     }
01001   } else if( d_translate && d_em->getOutputLang() == SMTLIB_V2_LANG ) {
01002     *d_osdump << "(set-info :status ";
01003     switch( qres ) {
01004     case UNSATISFIABLE:
01005       *d_osdump << "unsat";
01006       break;
01007     case SATISFIABLE:
01008       *d_osdump << "sat";
01009       break;
01010     default:
01011       *d_osdump << "unknown";
01012       break;
01013     }
01014     *d_osdump << ")" << endl;
01015   } else if( d_translate && d_em->getOutputLang() == SPASS_LANG ) {
01016     *d_osdump << "status(";
01017     switch( qres ) {
01018     case UNSATISFIABLE:
01019       *d_osdump << "unsatisfiable";
01020       break;
01021     case SATISFIABLE:
01022       *d_osdump << "satisfiable";
01023       break;
01024     default:
01025       *d_osdump << "unknown";
01026       break;
01027     }
01028     *d_osdump << ")." << endl;
01029   }
01030 }
01031 
01032 
01033 /*
01034 Expr Translator::spassPreprocess(const Expr& e, ExprMap<Expr>& mapping,
01035                                  vector<Expr>& functions,
01036                                  vector<Expr>& predicates)
01037 {
01038   if(e.getKind() == LET) {
01039     if(e.arity() != 2) {
01040       throw SmtlibException("Translator::spassPreprocess(): LET with arity != 2 not supported");
01041     }
01042     char name[80];
01043     snprintf(name, sizeof(name), "_cvc3_let%u", mapping.size());
01044     Expr id(ID, d_em->newStringExpr(name));
01045     cout << "ENCOUNTERED A LET:" << endl << id << endl;
01046     mapping.insert(e[0][0], e[0][1]);
01047     functions.push_back(Expr(CONST, id, e[1].getType().getExpr()));
01048     return spassPreprocess(e[1], mapping, functions, predicates);
01049   //} else if(e.getKind() == x) {
01050   } else if(e.arity() > 0) {
01051     vector<Expr> args;
01052     for(int i = 0, iend = e.arity(); i < iend; ++i) {
01053       args.push_back(spassPreprocess(e[i], mapping, functions, predicates));
01054     }
01055     Expr out(e.getOp(), args);
01056     return out;
01057   }
01058   return e;
01059 }
01060 */
01061 
01062 
01063 Expr Translator::processType(const Expr& e)
01064 {
01065   switch (e.getKind()) {
01066     case TYPEDECL:
01067       return e;
01068     case INT:
01069       if (d_convertToBV) {
01070         return d_theoryBitvector->newBitvectorType(d_convertToBV).getExpr();
01071       }
01072       if (d_theoryCore->getFlags()["convert2array"].getBool()) {
01073         return d_elementType->getExpr();
01074       }
01075       d_intUsed = true;
01076       break;
01077     case REAL:
01078       if (d_real2int) {
01079         d_intUsed = true;
01080         return d_theoryArith->intType().getExpr();
01081       }
01082       else {
01083         d_realUsed = true;
01084       }
01085       break;
01086     case SUBRANGE:
01087       d_unknown = true;
01088       break;
01089     case ARRAY:
01090       if (d_theoryCore->getFlags()["convert2array"].getBool()) {
01091         d_ax = true;
01092         return d_arrayType->getExpr();
01093       }
01094       if (e[0].getKind() == TYPEDECL) {
01095         DebugAssert(e[0].arity() == 1, "expected arity 1");
01096         if (e[0][0].getString() == "Index") {
01097           if (e[1].getKind() == TYPEDECL) {
01098             DebugAssert(e[1].arity() == 1, "expected arity 1");
01099             if (e[1][0].getString() == "Element") {
01100               d_ax = true;
01101               break;
01102             }
01103           }
01104         }
01105       }
01106       else if (isInt(Type(e[0]))) {
01107         if (isInt(Type(e[1]))) {
01108           d_intIntArray = true;
01109           break;
01110         }
01111         else if (isReal(Type(e[1]))) {
01112           d_intRealArray = true;
01113           break;
01114         }
01115         else if (isArray(Type(e[1])) &&
01116                  isInt(Type(e[1][0])) &&
01117                  isReal(Type(e[1][1]))) {
01118           d_intIntRealArray = true;
01119           break;
01120         }
01121       }
01122       else if (e[0].getKind() == BITVECTOR &&
01123                e[1].getKind() == BITVECTOR) {
01124         break;
01125       }
01126       d_unknown = true;
01127       break;
01128     default:
01129       break;
01130   }
01131   d_theoryCore->theoryOf(e)->setUsed();
01132   if (e.arity() == 0) return e;
01133   bool changed = false;
01134   vector<Expr> vec;
01135   for (int i = 0; i < e.arity(); ++i) {
01136     vec.push_back(processType(e[i]));
01137     if (vec.back() != e[i]) changed = true;
01138   }
01139   if (changed)
01140     return Expr(e.getOp(), vec);
01141   return e;
01142 }
01143 
01144 
01145 void Translator::finish()
01146 {
01147   bool qf_uf = false;
01148 
01149   if (d_translate) {
01150 
01151     if (d_em->getOutputLang() == SPASS_LANG) {
01152       *d_osdump << "status(";
01153       if (d_expResult == "invalid" ||
01154           d_expResult == "satisfiable" ||
01155           d_expResult == "sat")
01156         *d_osdump << "satisfiable";
01157       else if (d_expResult == "valid" ||
01158                d_expResult == "unsatisfiable" ||
01159                d_expResult == "unsat")
01160         *d_osdump << "unsatisfiable";
01161       else if (d_expResult != "")
01162         *d_osdump << "unknown";
01163       else if (status() == "invalid" ||
01164                status() == "satisfiable" ||
01165                status() == "sat")
01166         *d_osdump << "satisfiable";
01167       else if (status() == "valid" ||
01168                status() == "unsatisfiable" ||
01169                status() == "unsat")
01170         *d_osdump << "unsatisfiable";
01171       else *d_osdump << "unknown";
01172       *d_osdump << ")." << endl;
01173       *d_osdump << "description({* Unknown *})." << endl;
01174       *d_osdump << "end_of_list." << endl;
01175 
01176       vector<Expr> functions, predicates, sorts;
01177 
01178       for(vector<Expr>::reverse_iterator i = d_dumpExprs.rbegin(), iend = d_dumpExprs.rend(); i != iend; ++i) {
01179         Expr e = *i;
01180         switch(e.getKind()) {
01181         case TYPE:
01182           sorts.push_back(e);
01183           d_dumpExprs.erase(i.base() - 1);
01184           break;
01185         case CONST:
01186           if(e.arity() == 2) {
01187             if (e[1].getKind() == BOOLEAN ||
01188                 (e[1].getKind() == ARROW && e[1][e[1].arity()-1].getKind() == BOOLEAN)) {
01189               predicates.push_back(e);
01190             } else {
01191               functions.push_back(e);
01192             }
01193             d_dumpExprs.erase(i.base() - 1);
01194           } else {
01195             throw SmtlibException("Translator::finish: SPASS_LANG: CONST not implemented for arity != 2");
01196           }
01197           break;
01198         case ANNOTATION:
01199           if (d_theoryCore->getFlags()["trans-skip-difficulty"].getBool() &&
01200               e[0].getKind() == STRING_EXPR && e[0].getString() == "difficulty") {
01201             // do nothing; skip the difficulty annotation
01202           } else {
01203             *d_osdump << "%% ";
01204             *d_osdump << e[0];
01205             if (e.arity() > 1) {
01206               *d_osdump << ": " << e[1];
01207             }
01208           }
01209           d_dumpExprs.erase(i.base() - 1);
01210           break;
01211 
01212           /*
01213         case ASSERT:
01214         case QUERY: {
01215           ExprMap<Expr> m;
01216           *i = Expr(e.getKind(), spassPreprocess(e[0], m, functions, predicates));
01217           break;
01218         }
01219           */
01220 
01221         default:
01222           //*d_osdump << "DOING NOTHING FOR: " << e << endl;
01223           break;
01224         }
01225       }
01226 
01227       // add some built-ins for the translation
01228       // only arity matters for SPASS; the real type of _cvc3_ite is Bool -> 'a -> 'a -> 'a
01229       //Expr cvc3ite(CONST, Expr(ID, d_em->newStringExpr("_cvc3_ite")),
01230       //Expr(ARROW, vector<Expr>(4, d_theoryArith->intType().getExpr())));
01231       // only arity matters for SPASS; the real type of _cvc3_xor is
01232       // Bool -> Bool -> Bool, but we can't represent Bool-arg'ed
01233       // functions
01234       /*
01235       Expr cvc3xor(CONST, Expr(ID, d_em->newStringExpr("_cvc3_xor")),
01236                    Expr(ARROW, vector<Expr>(2, d_theoryArith->intType().getExpr())));
01237       //functions.push_back(cvc3ite);
01238       predicates.push_back(cvc3xor);
01239       */
01240 
01241       *d_osdump << endl;
01242       *d_osdump << "list_of_symbols." << endl;
01243       if(!functions.empty()) {
01244         *d_osdump << "functions[";
01245         vector<Expr>::reverse_iterator i = functions.rbegin(), iend = functions.rend();
01246         while(i != iend) {
01247           Expr e = *i;
01248           string name = e[0][0].getString();
01249           if(isReal(d_theoryCore->getBaseType(Type(e[1])))) {
01250             // SPASS guys want "np" prefix on arith vars
01251             name = "np" + name;
01252           }
01253           *d_osdump << "(" << name << "," << ( e[1].getKind() == ARROW ? e[1].arity()-1 : e[1].arity() ) << ")";
01254           if(++i != iend) {
01255             *d_osdump << ",";
01256           }
01257         }
01258         *d_osdump << "]." << endl;
01259       }
01260       if(!predicates.empty()) {
01261         *d_osdump << "predicates[";
01262         vector<Expr>::reverse_iterator i = predicates.rbegin(), iend = predicates.rend();
01263         while(i != iend) {
01264           Expr e = *i;
01265           *d_osdump << "(" << e[0][0].getString() << "," << e[1].arity() << ")";
01266           if(++i != iend) {
01267             *d_osdump << ",";
01268           }
01269         }
01270         *d_osdump << "]." << endl;
01271       }
01272       if(!sorts.empty()) {
01273         *d_osdump << "sorts[";
01274         vector<Expr>::reverse_iterator i = sorts.rbegin(), iend = sorts.rend();
01275         while(i != iend) {
01276           Expr e = *i;
01277           *d_osdump << e[0][0].getString();
01278           if(++i != iend) {
01279             *d_osdump << ",";
01280           }
01281         }
01282         *d_osdump << "]." << endl;
01283       }
01284       *d_osdump << "end_of_list." << endl;
01285 
01286       /*
01287       *d_osdump << endl;
01288       *d_osdump << "list_of_declarations." << endl;
01289       *d_osdump << "end_of_list." << endl;
01290       */
01291 
01292       // define an ITE operator for the translation
01293       /*
01294       *d_osdump << endl;
01295       *d_osdump << "list_of_formulae(axioms)." << endl;
01296       *d_osdump << "formula( forall([A,B],equiv(_cvc3_xor(A,B),not(equal(A,B)))) )." << endl;
01297       // *d_osdump << "formula(forall([A,B],equal(_cvc3_ite(\ntrue\n,A,B),A)))." << endl;
01298       // *d_osdump << "formula(forall([A,B],equal(_cvc3_ite(\nfalse\n,A,B),B)))." << endl;
01299       *d_osdump << "end_of_list." << endl;
01300       */
01301 
01302       *d_osdump << endl;
01303       *d_osdump << "list_of_formulae(conjectures)." << endl;
01304     }
01305 
01306     if (d_em->getOutputLang() == SMTLIB_LANG) {
01307       // Print the rest of the preamble for smt-lib benchmarks
01308 
01309       // Get status from expResult flag
01310       *d_osdump << "  :status ";
01311       if (d_expResult == "invalid" ||
01312           d_expResult == "satisfiable")
01313         *d_osdump << "sat";
01314       else if (d_expResult == "valid" ||
01315                d_expResult == "unsatisfiable")
01316         *d_osdump << "unsat";
01317       else if (status() != "") {
01318         *d_osdump << status();
01319       }
01320       else *d_osdump << "unknown";
01321       *d_osdump << endl;
01322 
01323       // difficulty
01324       //      *d_osdump << "  :difficulty { unknown }" << endl;
01325 
01326       // category
01327       if (category() != "") {
01328         *d_osdump << "  :category { ";
01329         *d_osdump << category() << " }" << endl;
01330       }
01331 
01332       // Create types for theory QF_AX if needed
01333       if (d_theoryCore->getFlags()["convert2array"].getBool()) {
01334         d_indexType = new Type(d_theoryCore->newTypeExpr("Index"));
01335         d_elementType = new Type(d_theoryCore->newTypeExpr("Element"));
01336         d_arrayType = new Type(arrayType(*d_indexType, *d_elementType));
01337       }
01338     }
01339 
01340     // Preprocess and compute logic for smt-lib
01341 
01342     if (!d_theoryCore->getFlags()["trans-skip-pp"].getBool())
01343     {
01344       ExprMap<Expr> cache;
01345       // Step 1: preprocess asserts, queries, and types
01346       vector<Expr>::iterator i = d_dumpExprs.begin(), iend = d_dumpExprs.end();
01347       for (; i != iend; ++i) {
01348         Expr e = *i;
01349         switch (e.getKind()) {
01350           case ASSERT: {
01351             Expr e2 = preprocess(e[0], cache);
01352             if (e[0] == e2) break;
01353             e2.getType();
01354             *i = Expr(ASSERT, e2);
01355             break;
01356           }
01357           case QUERY: {
01358             Expr e2 = preprocess(e[0].negate(), cache);
01359             if (e[0].negate() == e2) break;
01360             e2.getType();
01361             *i = Expr(QUERY, e2.negate());
01362             break;
01363           }
01364           case CONST: {
01365             DebugAssert(e.arity() == 2, "Expected CONST with arity 2");
01366             if (d_theoryCore->getFlags()["convert2array"].getBool()) break;
01367             Expr e2 = processType(e[1]);
01368             if (e[1] == e2) break;
01369             if (d_convertToBV) {
01370               Expr newName = Expr(ID, d_em->newStringExpr(e[0][0].getString()+"_bv"));
01371               *i = Expr(CONST, newName, e2);
01372             }
01373             else {
01374               *i = Expr(CONST, e[0], e2);
01375             }
01376             break;
01377           }
01378           default:
01379             break;
01380         }
01381       }
01382     }
01383 
01384     if (d_zeroVar) {
01385       d_dumpExprs.insert(d_dumpExprs.begin(),
01386                          Expr(CONST, Expr(ID, d_em->newStringExpr("cvc3Zero")),
01387                               processType(d_zeroVar->getType().getExpr())));
01388     }
01389 
01390     // Type inference over equality
01391     if (!d_unknown && d_theoryCore->getFlags()["convert2array"].getBool()) {
01392       bool changed;
01393       do {
01394         changed = false;
01395         unsigned i;
01396         for (i = 0; i < d_equalities.size(); ++i) {
01397           if (d_equalities[i][0].getKind() == UCONST &&
01398               d_arrayConvertMap->find(d_equalities[i][0].getName()) == d_arrayConvertMap->end()) {
01399             if (d_equalities[i][1].getKind() == READ) {
01400               changed = true;
01401               (*d_arrayConvertMap)[d_equalities[i][0].getName()] = *d_elementType;
01402             }
01403             else if (d_equalities[i][1].getKind() == UCONST) {
01404               map<string, Type>::iterator it = d_arrayConvertMap->find(d_equalities[i][1].getName());
01405               if (it != d_arrayConvertMap->end()) {
01406                 changed = true;
01407                 (*d_arrayConvertMap)[d_equalities[i][0].getName()] = (*it).second;
01408               }
01409             }
01410           }
01411           else if (d_equalities[i][1].getKind() == UCONST &&
01412                    d_arrayConvertMap->find(d_equalities[i][1].getName()) == d_arrayConvertMap->end()) {
01413             if (d_equalities[i][0].getKind() == READ) {
01414               changed = true;
01415               (*d_arrayConvertMap)[d_equalities[i][1].getName()] = *d_elementType;
01416             }
01417             else if (d_equalities[i][0].getKind() == UCONST) {
01418               map<string, Type>::iterator it = d_arrayConvertMap->find(d_equalities[i][0].getName());
01419               if (it != d_arrayConvertMap->end()) {
01420                 changed = true;
01421                 (*d_arrayConvertMap)[d_equalities[i][1].getName()] = (*it).second;
01422               }
01423             }
01424           }
01425         }
01426       } while (changed);
01427     }
01428 
01429     if (d_em->getOutputLang() == SMTLIB_LANG ||
01430         d_em->getOutputLang() == SMTLIB_V2_LANG) {
01431 
01432       // Step 2: If both int and real are used, try to separate them
01433       if ((!d_unknown && (d_intUsed && d_realUsed)) ||
01434           d_theoryCore->getFlags()["convert2array"].getBool() ||
01435           ( d_em->getOutputLang() == SMTLIB_V2_LANG &&
01436             d_langUsed > NOT_USED && d_langUsed <= LINEAR )) {
01437         ExprMap<Expr> cache;
01438         vector<Expr>::iterator i = d_dumpExprs.begin(), iend = d_dumpExprs.end();
01439         for (; i != iend; ++i) {
01440           Expr e = *i;
01441           switch (e.getKind()) {
01442             case ASSERT: {
01443               if (d_theoryCore->getFlags()["convert2array"].getBool()) break;
01444               Expr e2 = preprocess2(e[0], cache);
01445               e2.getType();
01446               *i = Expr(ASSERT, e2);
01447               break;
01448             }
01449             case QUERY: {
01450               if (d_theoryCore->getFlags()["convert2array"].getBool()) break;
01451               Expr e2 = preprocess2(e[0].negate(), cache);
01452               e2.getType();
01453               *i = Expr(QUERY, e2.negate());
01454               break;
01455             }
01456             case CONST: {
01457               if (!d_theoryCore->getFlags()["convert2array"].getBool()) break;
01458               map<string, Type>::iterator it = d_arrayConvertMap->find(e[0][0].getString());
01459               if (it != d_arrayConvertMap->end()) {
01460                 *i = Expr(CONST, e[0], (*it).second.getExpr());
01461               }
01462               else {
01463                 Expr e2 = processType(e[1]);
01464                 if (e[1] == e2) break;
01465                 *i = Expr(CONST, e[0], e2);
01466               }
01467               break;
01468             }
01469             default:
01470               break;
01471           }
01472         }
01473       }
01474       d_arithUsed = d_realUsed || d_intUsed || d_intConstUsed || (d_langUsed != NOT_USED);
01475 
01476       // Step 3: Go through the cases and figure out the right logic
01477       if (d_em->getOutputLang() == SMTLIB_LANG) {
01478         *d_osdump << "  :logic ";
01479       }
01480       else {// d_em->getOutputLang() == SMTLIB_V2_LANG
01481         *d_osdump << "(set-logic ";
01482       }
01483       if (d_unknown ||
01484           d_theoryRecords->theoryUsed() ||
01485           d_theorySimulate->theoryUsed() ||
01486           d_theoryDatatype->theoryUsed()) {
01487         *d_osdump << "unknown";
01488       }
01489       else {
01490         if ((d_ax && (d_arithUsed ||
01491                       d_theoryBitvector->theoryUsed() ||
01492                       d_theoryUF->theoryUsed())) ||
01493             (d_intIntArray && d_realUsed) ||
01494             (d_arithUsed && d_theoryBitvector->theoryUsed())) {
01495           *d_osdump << "unknown";
01496         }
01497         else {
01498           bool QF = false;
01499           bool A = false;
01500           bool UF = false;
01501           bool promote = d_theoryCore->getFlags()["promote"].getBool();
01502 
01503           if (!d_theoryQuant->theoryUsed()) {
01504             QF = true;
01505             *d_osdump << "QF_";
01506           }
01507 
01508           if (d_theoryArray->theoryUsed() && !d_convertArray) {
01509             A = true;
01510             *d_osdump << "A";
01511           }
01512 
01513           // Promote undefined subset logics
01514           else if (promote &&
01515                    !QF &&
01516                    !(d_arithUsed && d_realUsed && !d_intUsed && d_langUsed <= LINEAR) &&
01517                    !(d_arithUsed && !d_realUsed && d_intUsed && d_langUsed == NONLINEAR)) {
01518             A = true;
01519             *d_osdump << "A";
01520           }
01521 
01522           if (d_theoryUF->theoryUsed() ||
01523               (d_theoryArray->theoryUsed() && d_convertArray)) {
01524             UF = true;
01525             *d_osdump << "UF";
01526           }
01527 
01528           // Promote undefined subset logics
01529             else if (promote &&
01530                      !QF &&
01531                      !(d_arithUsed && d_realUsed && !d_intUsed && d_langUsed <= LINEAR)) {
01532               UF = true;
01533               *d_osdump << "UF";
01534             }
01535 
01536           if (d_arithUsed) {
01537             if (d_intUsed && d_realUsed) {
01538               if (d_langUsed < NONLINEAR) {
01539                 *d_osdump << "LIRA";
01540               }
01541               else *d_osdump << "NIRA";
01542             }
01543             else if (d_realUsed) {
01544               if (d_langUsed <= DIFF_ONLY) {
01545 
01546                 // Promote undefined subset logics
01547                  if (promote && !QF) {
01548                    *d_osdump << "LRA";
01549                  } else
01550 
01551                   *d_osdump << "RDL";
01552               }
01553               else if (d_langUsed <= LINEAR) {
01554                   *d_osdump << "LRA";
01555               }
01556               else {
01557 
01558                 // Promote undefined subset logics
01559                  if (promote && !QF) {
01560                    *d_osdump << "NIRA";
01561                  } else
01562 
01563                   *d_osdump << "NRA";
01564               }
01565             }
01566             else {
01567               if (QF && !A && UF && d_langUsed <= LINEAR) {
01568                 if (!d_realUsed && d_langUsed <= LINEAR && d_UFIDL_ok) {
01569                   *d_osdump << "IDL";
01570                 }
01571                 else {
01572                   *d_osdump << "LIA";
01573                 }
01574               }
01575               else if (d_langUsed <= DIFF_ONLY) {
01576 
01577                 // Promote undefined subset logics
01578                 if (promote && !QF) {
01579                   *d_osdump << "LIA";
01580                 }
01581                 else if (A) {
01582                   if (!UF) {
01583                     UF = true;
01584                     *d_osdump << "UF";
01585                   }
01586                   *d_osdump << "LIA";
01587                 } else
01588 
01589                   *d_osdump << "IDL";
01590               }
01591               else if (d_langUsed <= LINEAR) {
01592 
01593                 // Promote undefined subset logics
01594                  if (promote && QF && A && !UF) {
01595                    UF = true;
01596                    *d_osdump << "UF";
01597                  }
01598 
01599                 if (QF && !A && (!d_realUsed && d_langUsed <= LINEAR && d_UFIDL_ok)) {
01600                   *d_osdump << "UFIDL";
01601                 }
01602                 else {
01603                   *d_osdump << "LIA";
01604                 }
01605               }
01606               else {
01607                   *d_osdump << "NIA";
01608               }
01609             }
01610           }
01611           else if (d_theoryBitvector->theoryUsed()) {
01612 
01613             // Promote undefined subset logics
01614             if (promote && A && QF && !UF) {
01615               UF = true;
01616               *d_osdump << "UF";
01617             }
01618 
01619             *d_osdump << "BV";
01620           }
01621           else {
01622 
01623             if (d_ax) {
01624               *d_osdump << "X";
01625             }
01626 
01627             // Promote undefined subset logics
01628             else if (promote && (!QF || (A && UF))) {
01629               *d_osdump << "LIA";
01630             } else {
01631 
01632               // Default logic
01633               if (!A && !UF) {
01634                 UF = true;
01635                 *d_osdump << "UF";
01636               }
01637               qf_uf = QF && UF && (!A);
01638             }
01639           }
01640         }
01641       }
01642       if (d_em->getOutputLang() == SMTLIB_V2_LANG) {
01643         *d_osdump << ")";
01644       }
01645       *d_osdump << endl;
01646     }
01647 
01648     if (d_em->getOutputLang() == SMTLIB_V2_LANG) {
01649       // Print the rest of the set-info commands
01650 
01651       if (source() != "") {
01652         *d_osdump << "(set-info :source "
01653                   << quoteAnnotation(source())
01654                   << ')' << endl;
01655       }
01656 
01657       *d_osdump << "(set-info :smt-lib-version 2.0)" << endl;
01658 
01659       // Remove leading and trailing spaces from category
01660       string c = category();
01661       size_t i = 0, j = c.size();
01662       while (c[i] == ' ') {
01663         ++i; --j;
01664       }
01665       while (j > 0 && c[i+j-1] == ' ') --j;
01666       if (j > 0) {
01667         c = c.substr(i,j);
01668         *d_osdump << "(set-info :category \"" << c << "\")" << endl;
01669       }
01670 
01671 //       if (benchName() != "") {
01672 //         *d_osdump << "(set-info :name \"" << benchName() << "\")" << endl;
01673 //       }
01674 
01675       // Get status from expResult flag
01676       *d_osdump << "(set-info :status ";
01677       if (d_expResult == "invalid" ||
01678           d_expResult == "satisfiable")
01679         *d_osdump << "sat";
01680       else if (d_expResult == "valid" ||
01681                d_expResult == "unsatisfiable")
01682         *d_osdump << "unsat";
01683       else if (status() != "") {
01684         *d_osdump << status();
01685       }
01686       else *d_osdump << "unknown";
01687       *d_osdump << ")" << endl;
01688 
01689       // Create types for theory QF_AX if needed
01690       if (d_theoryCore->getFlags()["convert2array"].getBool()) {
01691         d_indexType = new Type(d_theoryCore->newTypeExpr("Index"));
01692         d_elementType = new Type(d_theoryCore->newTypeExpr("Element"));
01693         d_arrayType = new Type(arrayType(*d_indexType, *d_elementType));
01694       }
01695     }
01696 
01697     if (d_em->getOutputLang() == PRESENTATION_LANG) {
01698       // If we translate SMT-LIBv2 to PRESENTATION, we should set
01699       // "no-save-model" so that multiple-query benchmarks give
01700       // the same results in both languages.
01701       //
01702       // Translation the other way doesn't work, since SMT-LIBv2
01703       // doesn't support CVC3 presentation language semantics.
01704       if(d_theoryCore->getFlags()["no-save-model"].getBool()) {
01705         *d_osdump << "OPTION \"no-save-model\" 1;" << endl;
01706       }
01707     }
01708   }
01709 
01710   if (d_dump) {
01711     // Dump the actual expressions
01712     vector<Expr>::const_iterator i = d_dumpExprs.begin(), iend = d_dumpExprs.end();
01713     vector<Expr> assumps;
01714     bool skip_diff = d_theoryCore->getFlags()["trans-skip-difficulty"].getBool();
01715     for (; i != iend; ++i) {
01716       Expr e = *i;
01717       switch (e.getKind()) {
01718         case ASSERT: {
01719           if (d_combineAssump) {
01720             assumps.push_back(e[0]);
01721           }
01722           else {
01723             *d_osdump << e << endl;
01724           }
01725           break;
01726         }
01727         case QUERY: {
01728           if (!assumps.empty()) {
01729             assumps.push_back(e[0].negate());
01730             e = Expr(QUERY, Expr(NOT, Expr(AND, assumps)));
01731           }
01732           *d_osdump << e << endl;
01733           break;
01734         }
01735         default:
01736           if (d_em->getOutputLang() == SMTLIB_LANG &&
01737               qf_uf && e.getKind() == TYPE && e[0].getKind() == RAW_LIST &&
01738               e[0][0].getKind() == ID && e[0][0][0].getKind() == STRING_EXPR &&
01739               e[0][0][0].getString() == "U")
01740             break;
01741           if (d_em->getOutputLang() == SMTLIB_LANG &&
01742               d_ax && e.getKind() == TYPE && e[0].getKind() == RAW_LIST &&
01743               e[0][0].getKind() == ID && e[0][0][0].getKind() == STRING_EXPR &&
01744               ( e[0][0][0].getString() == "Index" ||
01745                 e[0][0][0].getString() == "Element" ))
01746             break;
01747           if (skip_diff && e.getKind() == ANNOTATION && e[0].getKind() == STRING_EXPR &&
01748               e[0].getString() == "difficulty")
01749             break;
01750           if (d_em->getOutputLang() == SMTLIB_V2_LANG &&
01751               (e.getKind() == CONST && e[0].getKind() == ID) &&
01752               (d_realUsed || d_intUsed)) {
01753             if (e[0][0].getString() == "abs") {
01754               // [MGD] Some benchmarks define their own abs, but we have to
01755               // rename it in the benchmark becuase in SMTLIBv2 the Reals and
01756               // Ints and Reals_Ints theories define abs.
01757               d_replaceSymbols["abs"] = "abs_";
01758             } else if (e[0][0].getString() == "mod") {
01759               // ditto for mod
01760               d_replaceSymbols["mod"] = "mod_";
01761             }
01762           }
01763           *d_osdump << e << endl;
01764           break;
01765       }
01766     }
01767   }
01768   if (d_translate) {
01769     if (d_em->getOutputLang() == SMTLIB_LANG) {
01770       *d_osdump << ")" << endl;
01771     }
01772     else if (d_em->getOutputLang() == SMTLIB_V2_LANG) {
01773       *d_osdump << "(exit)" << endl;
01774     }
01775 
01776     if (d_em->getOutputLang() == SPASS_LANG) {
01777       *d_osdump << "end_of_list." << endl;
01778       *d_osdump << endl;
01779       *d_osdump << "list_of_settings(SPASS)." << endl
01780                 << "{*" << endl
01781                 << "set_flag(Auto,1).    % auto configuration" << endl
01782                 << "set_flag(Splits,-1). % enable Splitting" << endl
01783                 << "set_flag(RVAA,1).    % enable variable assignment abstraction for LA" << endl
01784                 << "set_flag(RInput,0).  % no input reduction" << endl
01785                 << "set_flag(Sorts,0).   % no Sorts" << endl
01786                 << "set_flag(ISHy,0).    % no Hyper Resolution" << endl
01787                 << "set_flag(IOHy,0).    % no Hyper Resolution" << endl
01788                 << "set_flag(RTer,0).    % no Terminator" << endl
01789                 << "set_flag(RCon,0).    % no Condensation" << endl
01790                 << "set_flag(RFRew,1).   % no Contextual Rewriting" << endl
01791                 << "set_flag(RBRew,1).   % no Contextual Rewriting" << endl
01792                 << "*}" << endl
01793                 << "end_of_list." << endl;
01794       *d_osdump << endl;
01795       *d_osdump << "end_problem." << endl;
01796     }
01797   }
01798 
01799   if (d_dumpFileOpen) d_osdumpFile.close();
01800   if (d_zeroVar) delete d_zeroVar;
01801 }
01802 
01803 
01804 const string Translator::fixConstName(const string& s)
01805 {
01806   if (d_em->getOutputLang() == SMTLIB_LANG) {
01807     if (s[0] == '_') {
01808       return "smt"+s;
01809     }
01810   }
01811   std::hash_map<string, string, HashString>::iterator i = d_replaceSymbols.find(s);
01812   return (i == d_replaceSymbols.end()) ? s : (*i).second;
01813 }
01814 
01815 
01816 const string Translator::escapeSymbol(const string& s)
01817 {
01818   if (d_em->getOutputLang() == SMTLIB_V2_LANG) {
01819     if (s.length() == 0 || isdigit(s[0]))
01820       return "|" + s + "|";
01821     // This is the legal set of SMTLIB v2 symbol characters from page
01822     // 20 of the SMT-LIB v2.0 spec.  If any character in the symbol
01823     // string falls outside this set, the symbol must be |-delimited.
01824     if(s.find_first_not_of("abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789~!@$%^&*_-+=<>.?/") != string::npos)
01825       return "|" + s + "|";
01826   }
01827   return s;
01828 }
01829 
01830 const string Translator::quoteAnnotation(const string& s)
01831 {
01832   if(s.find('|') == string::npos) {
01833     return "|" + s + "|";
01834   } else {
01835     stringstream sb;
01836     sb << '"';
01837     for(string::const_iterator i = s.begin(); i != s.end(); ++i) {
01838       char c = *i;
01839       if(c == '"')
01840         sb << "\\\"";
01841       else
01842         sb << *i;
01843     }
01844     sb << '"';
01845     return sb.str();
01846   }
01847 }
01848 
01849 
01850 bool Translator::printArrayExpr(ExprStream& os, const Expr& e)
01851 {
01852   if (e.getKind() == ARRAY) {
01853     if (d_convertArray) {
01854       os << Expr(ARROW, e[0], e[1]);
01855       return true;
01856     }
01857     if (d_em->getOutputLang() == SMTLIB_V2_LANG) {
01858       DebugAssert( e.arity() == 2, "expected arity 2");
01859       os << push << "(Array" << space << nodag << e[0] << space << nodag << e[1] << ")" << pop;
01860       return true;
01861     }
01862     if (d_em->getOutputLang() != SMTLIB_LANG) return false;
01863     if (e[0].getKind() == TYPEDECL) {
01864       DebugAssert(e[0].arity() == 1, "expected arity 1");
01865       if (e[0][0].getString() == "Index") {
01866         if (e[1].getKind() == TYPEDECL) {
01867           DebugAssert(e[1].arity() == 1, "expected arity 1");
01868           if (e[1][0].getString() == "Element") {
01869             os << "Array";
01870             return true;
01871           }
01872         }
01873       }
01874     }
01875     else if (isInt(Type(e[0]))) {
01876       if (isInt(Type(e[1]))) {
01877         d_intIntArray = true;
01878         os << "Array";
01879         return true;
01880       }
01881       else if (isReal(Type(e[1]))) {
01882         d_intRealArray = true;
01883         os << "Array1";
01884         return true;
01885       }
01886       else if (isArray(Type(e[1])) &&
01887                isInt(Type(e[1][0])) &&
01888                isReal(Type(e[1][1]))) {
01889         d_intIntRealArray = true;
01890         os << "Array2";
01891         return true;
01892       }
01893     }
01894     else if (e[0].getKind() == BITVECTOR &&
01895              e[1].getKind() == BITVECTOR) {
01896       os << "Array[";
01897       os << d_theoryBitvector->getBitvectorTypeParam(Type(e[0]));
01898       os << ":";
01899       os << d_theoryBitvector->getBitvectorTypeParam(Type(e[1]));
01900       os << "]";
01901       return true;
01902     }
01903     os << "UnknownArray";
01904     d_unknown = true;
01905     return true;
01906   }
01907 
01908   switch (e.getKind()) {
01909     case READ:
01910       if (d_convertArray) {
01911         if (e[0].getKind() == UCONST) {
01912           os << Expr(d_em->newSymbolExpr(e[0].getName(), UFUNC).mkOp(), e[1]);
01913           return true;
01914         }
01915         else if (e[0].getKind() == WRITE) {
01916           throw Exception("READ of WRITE not implemented yet for convertArray");
01917         }
01918         else {
01919           throw Exception("Unexpected case for convertArray");
01920         }
01921       }
01922       break;
01923     case WRITE:
01924       if (d_convertArray) {
01925         throw Exception("WRITE expression encountered while attempting "
01926                         "to convert arrays to uninterpreted functions");
01927       }
01928       break;
01929     case ARRAY_LITERAL:
01930       if (d_convertArray) {
01931         throw Exception("ARRAY_LITERAL expression encountered while attempting"
01932                         " to convert arrays to uninterpreted functions");
01933       }
01934       break;
01935     default:
01936       throw Exception("Unexpected case in printArrayExpr");
01937       break;
01938   }
01939   return false;
01940 }
01941 
01942 
01943 Expr Translator::zeroVar()
01944 {
01945   if (!d_zeroVar) {
01946     d_zeroVar = new Expr();
01947     if (d_convertToDiff == "int") {
01948       *d_zeroVar = d_theoryCore->newVar("cvc3Zero", d_theoryArith->intType().getExpr());
01949     }
01950     else if (d_convertToDiff == "real") {
01951       *d_zeroVar = d_theoryCore->newVar("cvc3Zero", d_theoryArith->realType().getExpr());
01952     }
01953   }
01954   return *d_zeroVar;
01955 }