CVC3

theory_arith_old.cpp

Go to the documentation of this file.
00001 /*****************************************************************************/
00002 /*!
00003  * \file theory_arith_old.cpp
00004  *
00005  * Author: Clark Barrett, Vijay Ganesh.
00006  *
00007  * Created: Fri Jan 17 18:39:18 2003
00008  *
00009  * <hr>
00010  *
00011  * License to use, copy, modify, sell and/or distribute this software
00012  * and its documentation for any purpose is hereby granted without
00013  * royalty, subject to the terms and conditions defined in the \ref
00014  * LICENSE file provided with this distribution.
00015  *
00016  * <hr>
00017  *
00018  */
00019 /*****************************************************************************/
00020 
00021 
00022 #include "theory_arith_old.h"
00023 #include "arith_proof_rules.h"
00024 //#include "arith_expr.h"
00025 #include "arith_exception.h"
00026 #include "typecheck_exception.h"
00027 #include "eval_exception.h"
00028 #include "parser_exception.h"
00029 #include "smtlib_exception.h"
00030 #include "theory_core.h"
00031 #include "command_line_flags.h"
00032 //TODO: remove this dependency
00033 #include "../theory_core/core_proof_rules.h"
00034 
00035 
00036 using namespace std;
00037 using namespace CVC3;
00038 
00039 
00040 ///////////////////////////////////////////////////////////////////////////////
00041 // TheoryArithOld::FreeConst Methods                                            //
00042 ///////////////////////////////////////////////////////////////////////////////
00043 
00044 namespace CVC3 {
00045 
00046 ostream& operator<<(ostream& os, const TheoryArithOld::FreeConst& fc) {
00047   os << "FreeConst(r=" << fc.getConst() << ", "
00048      << (fc.strict()? "strict" : "non-strict") << ")";
00049   return os;
00050 }
00051 
00052 ///////////////////////////////////////////////////////////////////////////////
00053 // TheoryArithOld::Ineq Methods                                                 //
00054 ///////////////////////////////////////////////////////////////////////////////
00055 
00056 ostream& operator<<(ostream& os, const TheoryArithOld::Ineq& ineq) {
00057   os << "Ineq(" << ineq.ineq().getExpr() << ", isolated on "
00058      << (ineq.varOnRHS()? "RHS" : "LHS") << ", const = "
00059      << ineq.getConst() << ")";
00060   return os;
00061 }
00062 } // End of namespace CVC3
00063 
00064 
00065 ///////////////////////////////////////////////////////////////////////////////
00066 // TheoryArithOld Private Methods                                               //
00067 ///////////////////////////////////////////////////////////////////////////////
00068 
00069 
00070 Theorem TheoryArithOld::isIntegerThm(const Expr& e) {
00071   // Quick checks
00072   Type t = e.getType();
00073   if (isReal(t)) return Theorem();
00074   if (isInt(t)) return typePred(e);
00075 
00076   // Try harder
00077   return isIntegerDerive(Expr(IS_INTEGER, e), typePred(e));
00078 }
00079 
00080 
00081 Theorem TheoryArithOld::isIntegerDerive(const Expr& isIntE, const Theorem& thm) {
00082   const Expr& e = thm.getExpr();
00083   // We found it!
00084   if(e == isIntE) return thm;
00085 
00086   Theorem res;
00087   // If the theorem is an AND, look inside each child
00088   if(e.isAnd()) {
00089     int i, iend=e.arity();
00090     for(i=0; i<iend; ++i) {
00091       res = isIntegerDerive(isIntE, getCommonRules()->andElim(thm, i));
00092       if(!res.isNull()) return res;
00093     }
00094   }
00095   return res;
00096 }
00097 
00098 const Rational& TheoryArithOld::freeConstIneq(const Expr& ineq, bool varOnRHS) {
00099   DebugAssert(isIneq(ineq), "TheoryArithOld::freeConstIneq("+ineq.toString()+")");
00100   const Expr& e = varOnRHS? ineq[0] : ineq[1];
00101 
00102   switch(e.getKind()) {
00103   case PLUS:
00104     return e[0].getRational();
00105   case RATIONAL_EXPR:
00106     return e.getRational();
00107   default: { // MULT, DIV, or Variable
00108     static Rational zero(0);
00109     return zero;
00110   }
00111   }
00112 }
00113 
00114 
00115 const TheoryArithOld::FreeConst&
00116 TheoryArithOld::updateSubsumptionDB(const Expr& ineq, bool varOnRHS,
00117          bool& subsumed) {
00118   TRACE("arith ineq", "TheoryArithOld::updateSubsumptionDB(", ineq,
00119   ", var isolated on "+string(varOnRHS? "RHS" : "LHS")+")");
00120   DebugAssert(isLT(ineq) || isLE(ineq), "TheoryArithOld::updateSubsumptionDB("
00121         +ineq.toString()+")");
00122   // Indexing expression: same as ineq only without the free const
00123   Expr index;
00124   const Expr& t = varOnRHS? ineq[0] : ineq[1];
00125   bool strict(isLT(ineq));
00126   Rational c(0);
00127   if(isPlus(t)) {
00128     DebugAssert(t.arity() >= 2, "TheoryArithOld::updateSubsumptionDB("
00129     +ineq.toString()+")");
00130     c = t[0].getRational(); // Extract the free const in ineq
00131     Expr newT;
00132     if(t.arity() == 2) {
00133       newT = t[1];
00134     } else {
00135       vector<Expr> kids;
00136       Expr::iterator i=t.begin(), iend=t.end();
00137       kids.push_back(rat(0));
00138       for(++i; i!=iend; ++i) kids.push_back(*i);
00139       DebugAssert(kids.size() > 0, "kids.size = "+int2string(kids.size())
00140       +", ineq = "+ineq.toString());
00141       newT = plusExpr(kids);
00142     }
00143     if(varOnRHS)
00144       index = leExpr(rat(0), canonSimplify(ineq[1] - newT).getRHS());
00145     else
00146       index = leExpr(canonSimplify(ineq[0]-newT).getRHS(), rat(0));
00147   } else if(isRational(t)) {
00148     c = t.getRational();
00149     if(varOnRHS)
00150       index = leExpr(rat(0), ineq[1]);
00151     else
00152       index = leExpr(ineq[0], rat(0));
00153   } else if(isLT(ineq))
00154     index = leExpr(ineq[0], ineq[1]);
00155   else
00156     index = ineq;
00157   // Now update the database, check for subsumption, and extract the constant
00158   CDMap<Expr, FreeConst>::iterator i=d_freeConstDB.find(index),
00159     iend=d_freeConstDB.end();
00160   if(i == iend) {
00161     subsumed = false;
00162     // Create a new entry
00163     CDOmap<Expr,FreeConst>& obj = d_freeConstDB[index];
00164     obj = FreeConst(c,strict);
00165     TRACE("arith ineq", "freeConstDB["+index.toString()+"] := ", obj, "");
00166     return obj.get();
00167   } else {
00168     CDOmap<Expr,FreeConst>& obj = d_freeConstDB[index];
00169     const FreeConst& fc = obj.get();
00170     if(varOnRHS) {
00171       subsumed = (c < fc.getConst() ||
00172       (c == fc.getConst() && (!strict || fc.strict())));
00173     } else {
00174       subsumed = (c > fc.getConst() ||
00175       (c == fc.getConst() && (strict || !fc.strict())));
00176     }
00177     if(!subsumed) {
00178       obj = FreeConst(c,strict);
00179       TRACE("arith ineq", "freeConstDB["+index.toString()+"] := ", obj, "");
00180     }
00181     return obj.get();
00182   }
00183 }
00184 
00185 
00186 bool TheoryArithOld::kidsCanonical(const Expr& e) {
00187   if(isLeaf(e)) return true;
00188   bool res(true);
00189   for(int i=0; res && i<e.arity(); ++i) {
00190     Expr simp(canon(e[i]).getRHS());
00191     res = (e[i] == simp);
00192     IF_DEBUG(if(!res) debugger.getOS() << "\ne[" << i << "] = " << e[i]
00193        << "\nsimplified = " << simp << endl;)
00194   }
00195   return res;
00196 }
00197 
00198 
00199 ///////////////////////////////////////////////////////////////////////////////
00200 //                                                                           //
00201 // Function: TheoryArithOld::canon                                              //
00202 // Author: Clark Barrett, Vijay Ganesh.                                      //
00203 // Created: Sat Feb  8 14:46:32 2003                                         //
00204 // Description: Compute a canonical form for expression e and return a       //
00205 //              theorem that e is equal to its canonical form.               //
00206 // Note that canonical form for arith expressions is one of the following:   //
00207 // 1. rational constant                                                      //
00208 // 2. arithmetic leaf                                                        //
00209 //    (i.e. variable or term from some other theory)                         //
00210 // 3. (MULT rat leaf)                                                        //
00211 //    where rat is a non-zero rational constant, leaf is an arithmetic leaf  //
00212 // 4. (PLUS const term_0 term_1 ... term_n)                                  //
00213 //    where each term_i is either a leaf or (MULT rat leaf)                  //
00214 //    and each leaf in term_i must be strictly greater than the leaf in      //
00215 //    term_{i+1}.                                                            //
00216 //                                                                           //
00217 ///////////////////////////////////////////////////////////////////////////////
00218 Theorem TheoryArithOld::canon(const Expr& e)
00219 {
00220   TRACE("arith canon","canon(",e,") {");
00221   DebugAssert(kidsCanonical(e), "TheoryArithOld::canon("+e.toString()+")");
00222   Theorem result;
00223   switch (e.getKind()) {
00224     case UMINUS: {
00225       Theorem thm = d_rules->uMinusToMult(e[0]);
00226       Expr e2 = thm.getRHS();
00227       result = transitivityRule(thm, canon(e2));
00228     }
00229       break;
00230     case PLUS: /* {
00231       Theorem plusThm, plusThm1;
00232       plusThm = d_rules->canonFlattenSum(e);
00233       plusThm1 = d_rules->canonComboLikeTerms(plusThm.getRHS());
00234       result = transitivityRule(plusThm,plusThm1);
00235     }
00236              */
00237       result = d_rules->canonPlus(e);
00238       break;
00239     case MINUS: {
00240       DebugAssert(e.arity() == 2,"");
00241       Theorem minus_eq_sum = d_rules->minusToPlus(e[0], e[1]);
00242       // this produces e0 + (-1)*e1; we have to canonize it in 2 steps
00243       Expr sum(minus_eq_sum.getRHS());
00244       Theorem thm(canon(sum[1]));
00245       if(thm.getLHS() == thm.getRHS())
00246         result = canonThm(minus_eq_sum);
00247       // The sum changed; do the work
00248       else {
00249         vector<unsigned> changed;
00250         vector<Theorem> thms;
00251         changed.push_back(1);
00252         thms.push_back(thm);
00253         Theorem sum_eq_canon = canonThm(substitutivityRule(sum, changed, thms));
00254         result = transitivityRule(minus_eq_sum, sum_eq_canon);
00255       }
00256       break;
00257     }
00258 
00259     case MULT:
00260       result = d_rules->canonMult(e);
00261       break;
00262   /*
00263     case MULT: {
00264       Theorem thmMult, thmMult1;
00265       Expr exprMult;
00266       Expr e0 = e[0];
00267       Expr e1 = e[1];
00268       if(e0.isRational()) {
00269         if(rat(0) == e0)
00270         result = d_rules->canonMultZero(e1);
00271         else if (rat(1) == e0)
00272         result = d_rules->canonMultOne(e1);
00273         else
00274         switch(e1.getKind()) {
00275         case RATIONAL_EXPR :
00276           result = d_rules->canonMultConstConst(e0,e1);
00277           break;
00278         case MULT:
00279           DebugAssert(e1[0].isRational(),
00280                       "theory_arith::canon:\n  "
00281                       "canon:MULT:MULT child is not canonical: "
00282                       + e1[0].toString());
00283 
00284           thmMult = d_rules->canonMultConstTerm(e0,e1[0],e1[1]);
00285           result = transitivityRule(thmMult,canon(thmMult.getRHS()));
00286           break;
00287         case PLUS:{
00288           Theorem thmPlus, thmPlus1;
00289           Expr ePlus;
00290           std::vector<Theorem> thmPlusVector;
00291           thmPlus = d_rules->canonMultConstSum(e0,e1);
00292           ePlus = thmPlus.getRHS();
00293           Expr::iterator i = ePlus.begin();
00294           for(;i != ePlus.end();++i)
00295             thmPlusVector.push_back(canon(*i));
00296           thmPlus1 = substitutivityRule(PLUS, thmPlusVector);
00297           result = transitivityRule(thmPlus, thmPlus1);
00298           break;
00299         }
00300         default:
00301           result = reflexivityRule(e);
00302           break;
00303         }
00304       }
00305       else {
00306           if(e1.isRational()){
00307 
00308           // canonMultTermConst just reverses the order of the const and the
00309             // term.  Then canon is called again.
00310         Theorem t1 = d_rules->canonMultTermConst(e1,e0);
00311         result = transitivityRule(t1,canon(t1.getRHS()));
00312         }
00313         else
00314 
00315               // This is where the assertion for non-linear multiplication is
00316               // produced.
00317             result =  d_rules->canonMultTerm1Term2(e0,e1);
00318       }
00319       break;
00320       }
00321 
00322   */
00323     case DIVIDE:{
00324   /*
00325       case DIVIDE:{
00326         if (e[1].isRational()) {
00327           if (e[1].getRational() == 0)
00328             throw ArithException("Divide by 0 error in "+e.toString());
00329           Theorem thm = d_rules->canonDivideVar(e[0], e[1]);
00330           Expr e2 = thm.getRHS();
00331           result =  transitivityRule(thm, canon(e2));
00332         }
00333         else
00334         {
00335         // TODO: to be handled
00336         throw ArithException("Divide by a non-const not handled in "+e.toString());
00337         }
00338       break;
00339       }
00340   */
00341 
00342       // Division by 0 is OK (total extension, protected by TCCs)
00343       //      if (e[1].isRational() && e[1].getRational() == 0)
00344       //        throw ArithException("Divide by 0 error in "+e.toString());
00345       if (e[1].getKind() == PLUS)
00346         throw ArithException("Divide by a PLUS expression not handled in"+e.toString());
00347       result = d_rules->canonDivide(e);
00348       break;
00349     }
00350   case POW:
00351     if(e[1].isRational())
00352       result = d_rules->canonPowConst(e);
00353     else {
00354       // x ^ 1 --> x
00355       if (e[0].isRational() && e[0].getRational() == 1) {
00356         result = d_rules->powerOfOne(e);
00357       } else
00358         result = reflexivityRule(e);
00359     }
00360     break;
00361   default:
00362       result = reflexivityRule(e);
00363       break;
00364     }
00365   TRACE("arith canon","canon => ",result," }");
00366   return result;
00367 }
00368 
00369 
00370 Theorem
00371 TheoryArithOld::canonSimplify(const Expr& e) {
00372   TRACE("arith simplify", "canonSimplify(", e, ") {");
00373   DebugAssert(kidsCanonical(e),
00374         "TheoryArithOld::canonSimplify("+e.toString()+")");
00375   DebugAssert(leavesAreSimp(e), "Expected leaves to be simplified");
00376   Expr tmp(e);
00377   Theorem thm = canon(e);
00378   if(thm.getRHS().hasFind())
00379     thm = transitivityRule(thm, find(thm.getRHS()));
00380   // We shouldn't rely on simplification in this function anymore
00381   DebugAssert(thm.getRHS() == simplifyExpr(thm.getRHS()),
00382         "canonSimplify("+e.toString()+")\n"
00383         +"canon(e) = "+thm.getRHS().toString()
00384         +"\nsimplify(canon(e)) = "+simplifyExpr(thm.getRHS()).toString());
00385 //   if(tmp != thm.getRHS())
00386 //     thm = transitivityRule(thm, simplifyThm(thm.getRHS()));
00387 //   while(tmp != thm.getRHS()) {
00388 //     tmp = thm.getRHS();
00389 //     thm = canon(thm);
00390 //     if(tmp != thm.getRHS())
00391 //       thm = transitivityRule(thm, simplifyThm(thm.getRHS()));
00392 //   }
00393   TRACE("arith", "canonSimplify =>", thm, " }");
00394   return thm;
00395 }
00396 
00397 /*! accepts a theorem, canonizes it, applies iffMP and substituvity to
00398  *  derive the canonized thm
00399  */
00400 Theorem
00401 TheoryArithOld::canonPred(const Theorem& thm) {
00402   vector<Theorem> thms;
00403   DebugAssert(thm.getExpr().arity() == 2,
00404               "TheoryArithOld::canonPred: bad theorem: "+thm.toString());
00405   Expr e(thm.getExpr());
00406   thms.push_back(canonSimplify(e[0]));
00407   thms.push_back(canonSimplify(e[1]));
00408   Theorem result = iffMP(thm, substitutivityRule(e.getOp(), thms));
00409 
00410   return result;
00411 }
00412 
00413 /*! accepts an equivalence theorem, canonizes it, applies iffMP and
00414  *  substituvity to derive the canonized thm
00415  */
00416 Theorem
00417 TheoryArithOld::canonPredEquiv(const Theorem& thm) {
00418   vector<Theorem> thms;
00419   DebugAssert(thm.getRHS().arity() == 2,
00420               "TheoryArithOld::canonPredEquiv: bad theorem: "+thm.toString());
00421   Expr e(thm.getRHS());
00422   thms.push_back(canonSimplify(e[0]));
00423   thms.push_back(canonSimplify(e[1]));
00424   Theorem result = transitivityRule(thm, substitutivityRule(e.getOp(), thms));
00425 
00426   return result;
00427 }
00428 
00429 /*! accepts an equivalence theorem whose RHS is a conjunction,
00430  *  canonizes it, applies iffMP and substituvity to derive the
00431  *  canonized thm
00432  */
00433 Theorem
00434 TheoryArithOld::canonConjunctionEquiv(const Theorem& thm) {
00435   vector<Theorem> thms;
00436   return thm;
00437 }
00438 
00439 /*! Pseudo-code for doSolve. (Input is an equation) (output is a Theorem)
00440  *  -# translate e to the form e' = 0
00441  *  -# if (e'.isRational()) then {if e' != 0 return false else true}
00442  *  -# a for loop checks if all the variables are integers.
00443  *      - if not isolate a suitable real variable and call processRealEq().
00444  *      - if all variables are integers then isolate suitable variable
00445  *         and call processIntEq().
00446  */
00447 Theorem TheoryArithOld::doSolve(const Theorem& thm)
00448 {
00449   const Expr& e = thm.getExpr();
00450   if (e.isTrue() || e.isFalse()) return thm;
00451   TRACE("arith eq","doSolve(",e,") {");
00452   DebugAssert(thm.isRewrite(), "thm = "+thm.toString());
00453   Theorem eqnThm;
00454   vector<Theorem> thms;
00455   // Move LHS to the RHS, if necessary
00456   if(e[0].isRational() && e[0].getRational() == 0)
00457     eqnThm = thm;
00458   else {
00459     eqnThm = iffMP(thm, d_rules->rightMinusLeft(e));
00460     eqnThm = canonPred(eqnThm);
00461   }
00462   // eqnThm is of the form 0 = e'
00463   // 'right' is of the form e'
00464   Expr right = eqnThm.getRHS();
00465   // Check for trivial equation
00466   if (right.isRational()) {
00467     Theorem result = iffMP(eqnThm, d_rules->constPredicate(eqnThm.getExpr()));
00468     TRACE("arith eq","doSolve => ",result," }");
00469     return result;
00470   }
00471 
00472   //normalize
00473   eqnThm = iffMP(eqnThm, normalize(eqnThm.getExpr()));
00474   TRACE("arith eq","doSolve => ",eqnThm.getExpr()," }");
00475   right = eqnThm.getRHS();
00476 
00477   //eqn is of the form 0 = e' and is normalized where 'right' denotes e'
00478   //FIXME: change processRealEq to accept equations as well instead of theorems
00479 
00480   try {
00481     if (isMult(right)) {
00482       DebugAssert(right.arity() > 1, "Expected arity > 1");
00483       if (right[0].isRational()) {
00484         Rational r = right[0].getRational();
00485         if (r == 0) return getCommonRules()->trueTheorem();
00486         else if (r == 1) {
00487           enqueueFact(iffMP(eqnThm, d_rules->multEqZero(eqnThm.getExpr())));
00488           return getCommonRules()->trueTheorem();
00489         }
00490         Theorem res = iffMP(eqnThm,
00491                             d_rules->multEqn(eqnThm.getLHS(),
00492                                              right, rat(1/r)));
00493         res = canonPred(res);
00494         return doSolve(res);
00495       }
00496       else {
00497         enqueueFact(iffMP(eqnThm, d_rules->multEqZero(eqnThm.getExpr())));
00498         return getCommonRules()->trueTheorem();
00499       }
00500     }
00501     else if (isPow(right)) {
00502       DebugAssert(right.arity() == 2, "Expected arity 2");
00503       if (right[0].isRational()) {
00504         return doSolve(iffMP(eqnThm, d_rules->powEqZero(eqnThm.getExpr())));
00505       }
00506       throw ArithException("Can't solve exponential eqn: "+eqnThm.toString());
00507     }
00508     else {
00509       if(!isInteger(right)) {
00510         return processRealEq(eqnThm);
00511       }
00512       else {
00513         return processIntEq(eqnThm);
00514       }
00515     }
00516   } catch(ArithException& e) {
00517     FatalAssert(false, "We should never get here!!! : " + e.toString());
00518 
00519 //    // Nonlinear bail out
00520 //    Theorem res;
00521 //    if (isPlus(right)) {
00522 //      // Solve for something
00523 //      // Try to simulate groebner basis by picking the highest term
00524 //      Expr isolated = right[1];
00525 //      int isolated_degree = termDegree(isolated);
00526 //      for (int i = 2; i < right.arity(); i ++) {
00527 //        int degree = termDegree(right[i]);
00528 //        if (degree > isolated_degree) {
00529 //          isolated = right[i];
00530 //          isolated_degree = degree;
00531 //        }
00532 //      }
00533 //      Rational coeff;
00534 //      if (isMult(isolated) && isolated[0].isRational()) {
00535 //        coeff = isolated[0].getRational();
00536 //        DebugAssert(coeff != 0, "Expected nonzero coeff");
00537 //        isolated = canon(isolated / rat(coeff)).getRHS();
00538 //      } else coeff = 1;
00539 //      res = iffMP(eqnThm, d_rules->multEqn(rat(0), right, rat(-1/coeff)));
00540 //      res = canonPred(res);
00541 //      res = iffMP(res, d_rules->plusPredicate(res.getLHS(), res.getRHS(), isolated, EQ));
00542 //      res = canonPred(res);
00543 //      TRACE("arith nonlinear", "solved for: ", res.getExpr(), "");
00544 //    } else
00545 //      res = symmetryRule(eqnThm); // Flip to e' = 0
00546 //    TRACE("arith eq", "doSolve: failed to solve an equation: ", e, "");
00547 //    IF_DEBUG(debugger.counter("FAILED to solve equalities")++;)
00548 //    setIncomplete("Non-linear arithmetic equalities");
00549 //
00550 //    // Since we are forgetting about this equation, setup for updates
00551 //    TRACE("arith nonlinear", "adding setup to ", eqnThm.getExpr(), "");
00552 //    setupRec(eqnThm.getExpr());
00553 //    return getCommonRules()->trueTheorem();
00554   }
00555   FatalAssert(false, "");
00556   return Theorem();
00557 }
00558 
00559 /*! pick a monomial for the input equation. This function is used only
00560  *  if the equation is an integer equation. Choose the monomial with
00561  *  the smallest absolute value of coefficient.
00562  */
00563 bool TheoryArithOld::pickIntEqMonomial(const Expr& right, Expr& isolated, bool& nonlin)
00564 {
00565   DebugAssert(isPlus(right) && right.arity() > 1,
00566               "TheoryArithOld::pickIntEqMonomial right is wrong :-): " +
00567               right.toString());
00568   DebugAssert(right[0].isRational(),
00569               "TheoryArithOld::pickIntEqMonomial. right[0] must be const" +
00570               right.toString());
00571 //  DebugAssert(isInteger(right),
00572 //              "TheoryArithOld::pickIntEqMonomial: right is of type int: " +
00573 //              right.toString());
00574   //right is of the form "C + a1x1 + ... + anxn". min is initialized
00575   //to a1
00576   Expr::iterator istart = right.begin(), iend = right.end();
00577   istart++;
00578   Expr::iterator i = istart, j;
00579   bool found = false;
00580   nonlin = false;
00581   Rational min, coeff;
00582   Expr leaf;
00583   for(; i != iend; ++i) {
00584     if (isLeaf(*i)) {
00585       leaf = *i;
00586       coeff = 1;
00587     }
00588     else if (isMult(*i) && (*i).arity() == 2 && (*i)[0].isRational() && isLeaf((*i)[1])) {
00589       leaf = (*i)[1];
00590       coeff = abs((*i)[0].getRational());
00591     }
00592     else {
00593       nonlin = true;
00594       continue;
00595     }
00596     for (j = istart; j != iend; ++j) {
00597       if (j != i && isLeafIn(leaf, *j)) break;
00598     }
00599     if (j == iend) {
00600       if (!found || min > coeff) {
00601         min = coeff;
00602         isolated = *i;
00603         found = true;
00604       }
00605     }
00606   }
00607   return found;
00608 }
00609 
00610 /*! input is 0=e' Theorem and some of the vars in e' are of
00611  * type REAL. isolate one of them and send back to framework. output
00612  * is "var = e''" Theorem.
00613  */
00614 Theorem
00615 TheoryArithOld::processRealEq(const Theorem& eqn)
00616 {
00617   DebugAssert(eqn.getLHS().isRational() &&
00618               eqn.getLHS().getRational() == 0,
00619               "processRealEq invariant violated");
00620   Expr right = eqn.getRHS();
00621   // Find variable to isolate and store it in left.  Pick the largest
00622   // (according to the total ordering) variable.  FIXME: change from
00623   // total ordering to the ordering we devised for inequalities.
00624 
00625   // TODO: I have to pick a variable that appears as a variable in the
00626   // term but does not appear as a variable anywhere else.  The variable
00627   // must appear as a single leaf and not in a MULT expression with some
00628   // other variables and nor in a POW expression.
00629 
00630   bool found = false;
00631   Expr left;
00632 
00633   if (isPlus(right))  {
00634     DebugAssert(right[0].isRational(), "Expected first term to be rational");
00635     for(int i = 1, iend = right.arity(); i < iend; ++i) {
00636       Expr c = right[i];
00637       DebugAssert(!isRational(c), "Expected non-rational");
00638       if(!isInteger(c))  {
00639         if (isLeaf(c) ||
00640             ((isMult(c) && c.arity() == 2 && isLeaf(c[1])))) {
00641           Expr leaf = isLeaf(c) ? c : c[1];
00642           int j;
00643           for (j = 1; j < iend; ++j) {
00644             if (j!= i
00645     && isLeafIn(leaf, right[j])
00646     ) {
00647               break;
00648             }
00649           }
00650           if (j == iend) {
00651             left = c;
00652             found = true;
00653             break;
00654           }
00655         }
00656       }
00657     }
00658   }
00659   else if ((isMult(right) && right.arity() == 2 && isLeaf(right[1])) ||
00660            isLeaf(right)) {
00661     left = right;
00662     found = true;
00663   }
00664 
00665   if (!found) {
00666     // The only way we can not get an isolated in the reals is if all of them
00667     // are non-linear. In this case we might have some integers to solve for
00668     // so we try that. The integer solver shouldn't be able to solve for the
00669     // reals, as they are not solvable and we should be safe. One of such 
00670     // examples is if some constant ITE got skolemized and we have an equation
00671     // like SKOLEM = x^2 (bug79), in which case we should solve for the SKOLEM
00672   // where skolem is an INT variable.
00673     if (isNonlinearEq(eqn.getExpr()))
00674       return processIntEq(eqn);
00675     else throw
00676       ArithException("Can't find a leaf for solve in "+eqn.toString());
00677   }
00678 
00679   Rational r = -1;
00680   if (isMult(left))  {
00681     DebugAssert(left.arity() == 2, "only leaf should be chosen as lhs");
00682     DebugAssert(left[0].getRational() != 0, "left = "+left.toString());
00683     r = -1/left[0].getRational();
00684     left = left[1];
00685   }
00686 
00687   DebugAssert(isReal(getBaseType(left)) && !isInteger(left),
00688               "TheoryArithOld::ProcessRealEq: left is integer:\n left = "
00689         +left.toString());
00690   // Normalize equation so that coefficient of the monomial
00691   // corresponding to "left" in eqn[1] is -1
00692   Theorem result(iffMP(eqn,
00693            d_rules->multEqn(eqn.getLHS(), eqn.getRHS(), rat(r))));
00694   result = canonPred(result);
00695 
00696   // Isolate left
00697   result = iffMP(result, d_rules->plusPredicate(result.getLHS(),
00698             result.getRHS(), left, EQ));
00699   result = canonPred(result);
00700   TRACE("arith","processRealEq => ",result," }");
00701   return result;
00702 }
00703 
00704 
00705 void TheoryArithOld::getFactors(const Expr& e, set<Expr>& factors)
00706 {
00707   switch (e.getKind()) {
00708     case RATIONAL_EXPR: break;
00709     case MULT: {
00710       Expr::iterator i = e.begin(), iend = e.end();
00711       for (; i != iend; ++i) {
00712         getFactors(*i, factors);
00713       }
00714       break;
00715     }
00716     case POW: {
00717       DebugAssert(e.arity() == 2, "invariant violated");
00718       if (!isIntegerConst(e[0]) || e[0].getRational() <= 0) {
00719         throw ArithException("not positive integer exponent in "+e.toString());
00720       }
00721       if (isLeaf(e[1])) factors.insert(e[1]);
00722       break;
00723     }
00724     default: {
00725       DebugAssert(isLeaf(e), "expected leaf");
00726       DebugAssert(factors.find(e) == factors.end(), "expected new entry");
00727       factors.insert(e);
00728       break;
00729     }
00730   }
00731 }
00732 
00733 
00734 /*!
00735  * \param eqn is a single equation 0 = e
00736  * \return an equivalent Theorem (x = t AND 0 = e'), or just x = t
00737  */
00738 Theorem
00739 TheoryArithOld::processSimpleIntEq(const Theorem& eqn)
00740 {
00741   TRACE("arith eq", "processSimpleIntEq(", eqn.getExpr(), ") {");
00742   DebugAssert(eqn.isRewrite(),
00743               "TheoryArithOld::processSimpleIntEq: eqn must be equality" +
00744               eqn.getExpr().toString());
00745 
00746   Expr right = eqn.getRHS();
00747 
00748   DebugAssert(eqn.getLHS().isRational() && 0 == eqn.getLHS().getRational(),
00749               "TheoryArithOld::processSimpleIntEq: LHS must be 0:\n" +
00750               eqn.getExpr().toString());
00751 
00752   DebugAssert(!isMult(right) && !isPow(right), "should have been handled above");
00753   if (isPlus(right)) {
00754     if (2 == right.arity() &&
00755         (isLeaf(right[1]) ||
00756          (isMult(right[1]) && right[1].arity() == 2 && right[1][0].isRational() && isLeaf(right[1][1])))) {
00757       //we take care of special cases like 0 = c + a.x, 0 = c + x,
00758       Expr c,x;
00759       separateMonomial(right[1], c, x);
00760       Theorem isIntx(isIntegerThm(x));
00761       DebugAssert(!isIntx.isNull(), "right = "+right.toString()
00762       +"\n x = "+x.toString());
00763       Theorem res(iffMP(eqn, d_rules->intVarEqnConst(eqn.getExpr(), isIntx)));
00764       TRACE("arith eq", "processSimpleIntEq[0 = c + a*x] => ", res, " }");
00765       return res;
00766     }
00767     // Pick a suitable monomial. isolated can be of the form x, a.x, -a.x
00768     Expr isolated;
00769     bool nonlin;
00770     if (pickIntEqMonomial(right, isolated, nonlin)) {
00771       TRACE("arith eq", "processSimpleIntEq: isolated = ", isolated, "");
00772 
00773       // First, we compute the 'sign factor' with which to multiply the
00774       // eqn.  if the coeff of isolated is positive (i.e. 'isolated' is
00775       // of the form x or a.x where a>0 ) then r must be -1 and if coeff
00776       // of 'isolated' is negative, r=1.
00777       Rational r = isMult(isolated) ?
00778         ((isolated[0].getRational() > 0) ? -1 : 1) : -1;
00779       Theorem result;
00780       if (-1 == r) {
00781         // r=-1 and hence 'isolated' is 'x' or 'a.x' where a is
00782         // positive.  modify eqn (0=e') to the equation (0=canon(-1*e'))
00783         result = iffMP(eqn, d_rules->multEqn(eqn.getLHS(), right, rat(r)));
00784         result = canonPred(result);
00785         Expr e = result.getRHS();
00786 
00787         // Isolate the 'isolated'
00788         result = iffMP(result,
00789                        d_rules->plusPredicate(result.getLHS(),result.getRHS(),
00790               isolated, EQ));
00791       } else {
00792         //r is 1 and hence isolated is -a.x. Make 'isolated' positive.
00793         const Rational& minusa = isolated[0].getRational();
00794         Rational a = -1*minusa;
00795         isolated = (a == 1)? isolated[1] : rat(a) * isolated[1];
00796 
00797         // Isolate the 'isolated'
00798         result = iffMP(eqn, d_rules->plusPredicate(eqn.getLHS(),
00799                                                    right,isolated,EQ));
00800       }
00801       // Canonize the result
00802       result = canonPred(result);
00803 
00804       //if isolated is 'x' or 1*x, then return result else continue processing.
00805       if(!isMult(isolated) || isolated[0].getRational() == 1) {
00806         TRACE("arith eq", "processSimpleIntEq[x = rhs] => ", result, " }");
00807         return result;
00808       } else if (!nonlin) {
00809         DebugAssert(isMult(isolated) && isolated[0].getRational() >= 2,
00810                     "TheoryArithOld::processSimpleIntEq: isolated must be mult "
00811                     "with coeff >= 2.\n isolated = " + isolated.toString());
00812 
00813         // Compute IS_INTEGER() for lhs and rhs
00814         Expr lhs = result.getLHS();
00815         Expr rhs = result.getRHS();
00816         Expr a, x;
00817         separateMonomial(lhs, a, x);
00818         Theorem isIntLHS = isIntegerThm(x);
00819         vector<Theorem> isIntRHS;
00820         if(!isPlus(rhs)) { // rhs is a MULT
00821           Expr c, v;
00822           separateMonomial(rhs, c, v);
00823           isIntRHS.push_back(isIntegerThm(v));
00824           DebugAssert(!isIntRHS.back().isNull(), "");
00825         } else { // rhs is a PLUS
00826           DebugAssert(isPlus(rhs), "rhs = "+rhs.toString());
00827           DebugAssert(rhs.arity() >= 2, "rhs = "+rhs.toString());
00828           Expr::iterator i=rhs.begin(), iend=rhs.end();
00829           ++i; // Skip the free constant
00830           for(; i!=iend; ++i) {
00831             Expr c, v;
00832             separateMonomial(*i, c, v);
00833             isIntRHS.push_back(isIntegerThm(v));
00834             DebugAssert(!isIntRHS.back().isNull(), "");
00835           }
00836         }
00837         // Derive (EXISTS (x:INT): x = t2 AND 0 = t3)
00838         result = d_rules->eqElimIntRule(result, isIntLHS, isIntRHS);
00839         // Skolemize the quantifier
00840         result = getCommonRules()->skolemize(result);
00841         // Canonize t2 and t3 generated by this rule
00842         DebugAssert(result.getExpr().isAnd() && result.getExpr().arity() == 2,
00843                     "processSimpleIntEq: result = "+result.getExpr().toString());
00844         Theorem thm1 = canonPred(getCommonRules()->andElim(result, 0));
00845         Theorem thm2 = canonPred(getCommonRules()->andElim(result, 1));
00846         Theorem newRes = getCommonRules()->andIntro(thm1, thm2);
00847         if(newRes.getExpr() != result.getExpr()) result = newRes;
00848 
00849         TRACE("arith eq", "processSimpleIntEq => ", result, " }");
00850         return result;
00851       }
00852     }
00853     throw
00854       ArithException("Can't find a leaf for solve in "+eqn.toString());
00855   } else {
00856     // eqn is 0 = x.  Flip it and return
00857     Theorem result = symmetryRule(eqn);
00858     TRACE("arith eq", "processSimpleIntEq[x = 0] => ", result, " }");
00859     return result;
00860   }
00861 }
00862 
00863 /*! input is 0=e' Theorem and all of the vars in e' are of
00864  * type INT. isolate one of them and send back to framework. output
00865  * is "var = e''" Theorem and some associated equations in
00866  * solved form.
00867  */
00868 Theorem
00869 TheoryArithOld::processIntEq(const Theorem& eqn)
00870 {
00871   TRACE("arith eq", "processIntEq(", eqn.getExpr(), ") {");
00872   // Equations in the solved form.
00873   std::vector<Theorem> solvedAndNewEqs;
00874   Theorem newEq(eqn), result;
00875   bool done(false);
00876   do {
00877     result = processSimpleIntEq(newEq);
00878     // 'result' is of the from (x1=t1)  AND 0=t'
00879     if(result.isRewrite()) {
00880       solvedAndNewEqs.push_back(result);
00881       done = true;
00882     }
00883     else if (result.getExpr().isBoolConst()) {
00884       done = true;
00885     }
00886     else {
00887       DebugAssert(result.getExpr().isAnd() && result.getExpr().arity() == 2,
00888       "TheoryArithOld::processIntEq("+eqn.getExpr().toString()
00889       +")\n result = "+result.getExpr().toString());
00890       solvedAndNewEqs.push_back(getCommonRules()->andElim(result, 0));
00891       newEq = getCommonRules()->andElim(result, 1);
00892     }
00893   } while(!done);
00894   Theorem res;
00895   if (result.getExpr().isFalse()) res = result;
00896   else if (solvedAndNewEqs.size() > 0)
00897     res = solvedForm(solvedAndNewEqs);
00898   else res = result;
00899   TRACE("arith eq", "processIntEq => ", res.getExpr(), " }");
00900   return res;
00901 }
00902 
00903 /*!
00904  * Takes a vector of equations and for every equation x_i=t_i
00905  * substitutes t_j for x_j in t_i for all j>i.  This turns the system
00906  * of equations into a solved form.
00907  *
00908  * Assumption: variables x_j may appear in the RHS terms t_i ONLY for
00909  * i<j, but not for i>=j.
00910  */
00911 Theorem
00912 TheoryArithOld::solvedForm(const vector<Theorem>& solvedEqs)
00913 {
00914   DebugAssert(solvedEqs.size() > 0, "TheoryArithOld::solvedForm()");
00915 
00916   // Trace code
00917   TRACE_MSG("arith eq", "TheoryArithOld::solvedForm:solvedEqs(\n  [");
00918   IF_DEBUG(if(debugger.trace("arith eq")) {
00919     for(vector<Theorem>::const_iterator j = solvedEqs.begin(),
00920     jend=solvedEqs.end(); j!=jend;++j)
00921       TRACE("arith eq", "", j->getExpr(), ",\n   ");
00922   })
00923   TRACE_MSG("arith eq", "  ]) {");
00924   // End of Trace code
00925 
00926   vector<Theorem>::const_reverse_iterator
00927     i = solvedEqs.rbegin(),
00928     iend = solvedEqs.rend();
00929   // Substitution map: a variable 'x' is mapped to a Theorem x=t.
00930   // This map accumulates the resulting solved form.
00931   ExprMap<Theorem> subst;
00932   for(; i!=iend; ++i) {
00933     if(i->isRewrite()) {
00934       Theorem thm = substAndCanonize(*i, subst);
00935       TRACE("arith eq", "solvedForm: subst["+i->getLHS().toString()+"] = ",
00936       thm.getExpr(), "");
00937       subst[i->getLHS()] = thm;
00938     }
00939     else {
00940       // This is the FALSE case: just return the contradiction
00941       DebugAssert(i->getExpr().isFalse(),
00942       "TheoryArithOld::solvedForm: an element of solvedEqs must "
00943       "be either EQ or FALSE: "+i->toString());
00944       return *i;
00945     }
00946   }
00947   // Now we've collected the solved form in 'subst'.  Wrap it up into
00948   // a conjunction and return.
00949   vector<Theorem> thms;
00950   for(ExprMap<Theorem>::iterator i=subst.begin(), iend=subst.end();
00951       i!=iend; ++i)
00952     thms.push_back(i->second);
00953 
00954   if (thms.size() > 1) return getCommonRules()->andIntro(thms);
00955   else return thms.back();
00956 }
00957 
00958 
00959 /*!
00960  * ASSUMPTION: 't' is a fully canonized arithmetic term, and every
00961  * element of subst is a fully canonized equation of the form x=e,
00962  * indexed by the LHS variable.
00963  */
00964 
00965 Theorem
00966 TheoryArithOld::substAndCanonize(const Expr& t, ExprMap<Theorem>& subst)
00967 {
00968   TRACE("arith eq", "substAndCanonize(", t, ") {");
00969   // Quick and dirty check: return immediately if subst is empty
00970   if(subst.empty()) {
00971     Theorem res(reflexivityRule(t));
00972     TRACE("arith eq", "substAndCanonize[subst empty] => ", res, " }");
00973     return res;
00974   }
00975   // Check if we can substitute 't' directly
00976   ExprMap<Theorem>::iterator i = subst.find(t), iend=subst.end();
00977   if(i!=iend) {
00978     TRACE("arith eq", "substAndCanonize[subst] => ", i->second, " }");
00979     return i->second;
00980   }
00981   // The base case: t is an i-leaf
00982   if(isLeaf(t)) {
00983     Theorem res(reflexivityRule(t));
00984     TRACE("arith eq", "substAndCanonize[i-leaf] => ", res, " }");
00985     return res;
00986   }
00987   // 't' is an arithmetic term; recurse into the children
00988   vector<Theorem> thms;
00989   vector<unsigned> changed;
00990   for(unsigned j=0, jend=t.arity(); j!=jend; ++j) {
00991     Theorem thm = substAndCanonize(t[j], subst);
00992     if(thm.getRHS() != t[j]) {
00993       thm = canonThm(thm);
00994       thms.push_back(thm);
00995       changed.push_back(j);
00996     }
00997   }
00998   // Do the actual substitution and canonize the result
00999   Theorem res;
01000   if(thms.size() > 0) {
01001     res = substitutivityRule(t, changed, thms);
01002     res = canonThm(res);
01003   }
01004   else
01005     res = reflexivityRule(t);
01006   TRACE("arith eq", "substAndCanonize => ", res, " }");
01007   return res;
01008 }
01009 
01010 
01011 /*!
01012  *  ASSUMPTION: 't' is a fully canonized equation of the form x = t,
01013  *  and so is every element of subst, indexed by the LHS variable.
01014  */
01015 
01016 Theorem
01017 TheoryArithOld::substAndCanonize(const Theorem& eq, ExprMap<Theorem>& subst)
01018 {
01019   // Quick and dirty check: return immediately if subst is empty
01020   if(subst.empty()) return eq;
01021 
01022   DebugAssert(eq.isRewrite(), "TheoryArithOld::substAndCanonize: t = "
01023         +eq.getExpr().toString());
01024   const Expr& t = eq.getRHS();
01025   // Do the actual substitution in the term t
01026   Theorem thm = substAndCanonize(t, subst);
01027   // Substitution had no result: return the original equation
01028   if(thm.getRHS() == t) return eq;
01029   // Otherwise substitute the result into the equation
01030   vector<Theorem> thms;
01031   vector<unsigned> changed;
01032   thms.push_back(thm);
01033   changed.push_back(1);
01034   return iffMP(eq, substitutivityRule(eq.getExpr(), changed, thms));
01035 }
01036 
01037 void TheoryArithOld::processBuffer()
01038 {
01039   // Process the inequalities in the buffer
01040   bool varOnRHS;
01041 
01042   // If we are in difference logic only, just return
01043   if (diffLogicOnly) return;
01044 
01045   while (!inconsistent() && (d_bufferIdx_0 < d_buffer_0.size() || d_bufferIdx_1 < d_buffer_1.size() || d_bufferIdx_2 < d_buffer_2.size() ||  d_bufferIdx_3 < d_buffer_3.size())) {
01046 
01047     // Get the unprojected inequality
01048     Theorem ineqThm;
01049     if (d_bufferIdx_0 < d_buffer_0.size()) {
01050       ineqThm = d_buffer_0[d_bufferIdx_0];
01051         d_bufferIdx_0 = d_bufferIdx_0 + 1;
01052     } else if (d_bufferIdx_1 < d_buffer_1.size()) {
01053       ineqThm = d_buffer_1[d_bufferIdx_1];
01054       d_bufferIdx_1 = d_bufferIdx_1 + 1;
01055     } else if (d_bufferIdx_2 < d_buffer_2.size()) {
01056       ineqThm = d_buffer_2[d_bufferIdx_2];
01057       d_bufferIdx_2 = d_bufferIdx_2 + 1;
01058     } else {
01059       ineqThm = d_buffer_3[d_bufferIdx_3];
01060       d_bufferIdx_3 = d_bufferIdx_3 + 1;
01061     }
01062 
01063 //    // Skip this inequality if it is stale
01064 //    if(isStale(ineqThm.getExpr())) {
01065 //      TRACE("arith buffer", "processBuffer(", ineqThm.getExpr(), ")... skipping stale");
01066 //      continue;
01067 //    }
01068     // Dejan: project the finds, not the originals (if not projected already)
01069     const Expr& inequality = ineqThm.getExpr();
01070     Theorem inequalityFindThm = inequalityToFind(ineqThm, true);
01071     Expr inequalityFind = inequalityFindThm.getExpr();
01072 //    if (inequality != inequalityFind)
01073 //      enqueueFact(inequalityFindThm);
01074 
01075     TRACE("arith buffer", "processing: ", inequality, "");
01076     TRACE("arith buffer", "with find : ", inequalityFind, "");
01077 
01078     if (!isIneq(inequalityFind)) {
01079       TRACE("arith buffer", "find not an inequality... ", "", "skipping");
01080       continue;
01081     }
01082 
01083     if (alreadyProjected.find(inequalityFind) != alreadyProjected.end()) {
01084       TRACE("arith buffer", "already projected ... ", "", "skipping");
01085       continue;
01086     }
01087 
01088 
01089     // We put the dummy for now, isolate variable will set it properly (or the find's one)
01090     // This one is just if the find is different. If the find is different
01091     // We will not check it again in update, so we're fine
01092   Expr dummy;
01093     alreadyProjected[inequality] = dummy;
01094     if (inequality != inequalityFind) {
01095 
01096       alreadyProjected[inequalityFind] = dummy;
01097 
01098       Expr rhs = inequalityFind[1];
01099 
01100       // Collect the statistics about variables
01101       if(isPlus(rhs)) {
01102           for(Expr::iterator i=rhs.begin(), iend=rhs.end(); i!=iend; ++i) {
01103             Expr monomial = *i;
01104             updateStats(monomial);
01105           }
01106       } else // It's a monomial
01107           updateStats(rhs);
01108     }
01109 
01110     // See if this one is subsumed by a stronger inequality
01111     // c1 <= t1, t2 <= c2
01112     Rational c1, c2;
01113     Expr t1, t2;
01114     // Every term in the buffer has to have a lower bound set!!!
01115     // Except for the ones that changed the find
01116     extractTermsFromInequality(inequalityFind, c1, t1, c2, t2);
01117     if (termLowerBound.find(t1) != termLowerBound.end() && c1 != termLowerBound[t1]) {
01118       TRACE("arith ineq", "skipping because stronger bounds asserted ", inequalityFind.toString(), ":" + t1.toString());
01119       DebugAssert(termLowerBoundThm.find(t1) != termLowerBoundThm.end(), "No lower bound on asserted atom!!! " + t1.toString());
01120       Theorem strongerBound = termLowerBoundThm[t1];
01121       //enqueueFact(d_rules->implyWeakerInequality(strongerBound.getExpr(), inequalityFindThm.getExpr()));
01122       continue;
01123     }
01124 
01125     Theorem thm1 = isolateVariable(inequalityFindThm, varOnRHS);
01126     const Expr& ineq = thm1.getExpr();
01127     if (ineq.isFalse())
01128       setInconsistent(thm1);
01129     else
01130       if(!ineq.isTrue()) {
01131 
01132         // Check that the variable is indeed isolated correctly
01133         DebugAssert(varOnRHS? !isPlus(ineq[1]) : !isPlus(ineq[0]), "TheoryArithOld::processBuffer(): bad result from isolateVariable:\nineq = "+ineq.toString());
01134         // and project the inequality
01135         projectInequalities(thm1, varOnRHS);
01136       }
01137     }
01138 }
01139 
01140 
01141 void TheoryArithOld::updateStats(const Rational& c, const Expr& v)
01142 {
01143   TRACE("arith stats", "updateStats("+c.toString()+", ", v, ")");
01144 
01145   // we can get numbers as checking for variables is not possible (nonlinear stuff)
01146   if (v.isRational()) return;
01147 
01148   if (v.getType() != d_realType) {
01149     // Dejan: update the max coefficient of the variable
01150     if (c < 0) {
01151       // Goes to the left side
01152       ExprMap<Rational>::iterator maxFind = maxCoefficientLeft.find(v);
01153       if (maxFind == maxCoefficientLeft.end()) {
01154         maxCoefficientLeft[v] = - c;
01155         TRACE("arith stats", "max left", "", "");
01156       }
01157       else
01158         if ((*maxFind).second < -c) {
01159           TRACE("arith stats", "max left", "", "");
01160           maxCoefficientLeft[v] = -c;
01161         }
01162     } else {
01163       // Stays on the right side
01164       ExprMap<Rational>::iterator maxFind = maxCoefficientRight.find(v);
01165       if (maxFind == maxCoefficientRight.end()) {
01166         maxCoefficientRight[v] = c;
01167         TRACE("arith stats", "max right", "", "");
01168       }
01169       else
01170         if((*maxFind).second < c) {
01171           TRACE("arith stats", "max right", "", "");
01172           maxCoefficientRight[v] = c;
01173         }
01174     }
01175   }
01176 
01177   if(c > 0) {
01178     if(d_countRight.count(v) > 0) d_countRight[v] = d_countRight[v] + 1;
01179     else d_countRight[v] = 1;
01180   }
01181   else
01182     if(d_countLeft.count(v) > 0) d_countLeft[v] = d_countLeft[v] + 1;
01183     else d_countLeft[v] = 1;
01184 }
01185 
01186 
01187 void TheoryArithOld::updateStats(const Expr& monomial)
01188 {
01189   Expr c, m;
01190   separateMonomial(monomial, c, m);
01191   updateStats(c.getRational(), m);
01192 }
01193 
01194 int TheoryArithOld::extractTermsFromInequality(const Expr& inequality,
01195     Rational& c1, Expr& t1,
01196     Rational& c2, Expr& t2) {
01197 
01198   TRACE("arith extract", "extract(", inequality.toString(), ")");
01199 
01200   DebugAssert(isIneq(inequality), "extractTermsFromInequality: expexting an inequality got: " + inequality.getString() + ")");
01201 
01202   Expr rhs = inequality[1];
01203 
01204   c1 = 0;
01205 
01206   // Extract the non-constant term (both sides)
01207   vector<Expr> positive_children, negative_children;
01208   if (isPlus(rhs)) {
01209       int start_i = 0;
01210       if (rhs[0].isRational()) {
01211         start_i = 1;
01212         c1 = -rhs[0].getRational();
01213       }
01214       int end_i   = rhs.arity();
01215         for(int i = start_i; i < end_i; i ++) {
01216           const Expr& term = rhs[i];
01217           positive_children.push_back(term);
01218           negative_children.push_back(canon(multExpr(rat(-1),term)).getRHS());
01219         }
01220     } else {
01221         positive_children.push_back(rhs);
01222       negative_children.push_back(canon(multExpr(rat(-1), rhs)).getRHS());
01223     }
01224 
01225     int num_vars = positive_children.size();
01226 
01227     // c1 <= t1
01228     t1 = (num_vars > 1 ? canon(plusExpr(positive_children)).getRHS() : positive_children[0]);
01229 
01230     // c2 is the upper bound on t2 : t2 <= c2
01231     c2 = -c1;
01232     t2 = (num_vars > 1 ? canon(plusExpr(negative_children)).getRHS() : negative_children[0]);
01233 
01234     TRACE("arith extract", "extract: ", c1.toString() + " <= ", t1.toString());
01235 
01236     return num_vars;
01237 }
01238 
01239 bool TheoryArithOld::addToBuffer(const Theorem& thm, bool priority) {
01240 
01241   TRACE("arith buffer", "addToBuffer(", thm.getExpr().toString(), ")");
01242 
01243   Expr ineq = thm.getExpr();
01244   const Expr& rhs = thm.getExpr()[1];
01245 
01246   bool nonLinear = false;
01247   Rational nonLinearConstant = 0;
01248   Expr compactNonLinear;
01249   Theorem compactNonLinearThm;
01250 
01251   // Collect the statistics about variables and check for non-linearity
01252   if(isPlus(rhs)) {
01253     for(Expr::iterator i=rhs.begin(), iend=rhs.end(); i!=iend; ++i) {
01254       Expr monomial = *i;
01255       updateStats(monomial);
01256       // check for non-linear
01257       if (isMult(monomial)) {
01258         if ((monomial[0].isRational() && monomial.arity() >= 3) ||
01259           (!monomial[0].isRational() && monomial.arity() >= 2) ||
01260           (monomial.arity() == 2 && isPow(monomial[1])))
01261           nonLinear = true;
01262       }
01263     }
01264     if (nonLinear) {
01265       compactNonLinearThm = d_rules->compactNonLinearTerm(rhs);
01266       compactNonLinear = compactNonLinearThm.getRHS();
01267     }
01268   }
01269   else // It's a monomial
01270   {
01271     updateStats(rhs);
01272   if (isMult(rhs))
01273     if ((rhs[0].isRational() && rhs.arity() >= 3)
01274         || (!rhs[0].isRational() && rhs.arity() >= 2)
01275         || (rhs.arity() == 2 && isPow(rhs[1]))) {
01276       nonLinear = true;
01277       compactNonLinear = rhs;
01278       compactNonLinearThm = reflexivityRule(compactNonLinear);
01279     }
01280   }
01281 
01282   if (bufferedInequalities.find(ineq) != bufferedInequalities.end()) {
01283     TRACE("arith buffer", "addToBuffer()", "", "... already in db");
01284     if (formulaAtoms.find(ineq) != formulaAtoms.end()) {
01285       TRACE("arith buffer", "it's a formula atom, enqueuing.", "", "");
01286       enqueueFact(thm);
01287     }
01288     return false;
01289   }
01290 
01291   if (nonLinear && (isMult(rhs) || compactNonLinear != rhs)) {
01292     TRACE("arith nonlinear", "compact version of ", rhs, " is " + compactNonLinear.toString());
01293     // Replace the rhs with the compacted nonlinear term
01294     Theorem thm1 = (compactNonLinear != rhs ?
01295         iffMP(thm, substitutivityRule(ineq, 1, compactNonLinearThm)) : thm);
01296     // Now, try to deduce the signednes of multipliers
01297     Rational c = (isMult(rhs) ? 0 : compactNonLinear[0].getRational());
01298     // We can deduct the signs if the constant is not bigger than 0
01299     if (c <= 0) {
01300       thm1 = d_rules->nonLinearIneqSignSplit(thm1);
01301       TRACE("arith nonlinear", "spliting on signs : ", thm1.getExpr(), "");
01302       enqueueFact(thm1);
01303     }
01304   }
01305 
01306   // Get c1, c2, t1, t2 such that c1 <= t1 and t2 <= c2
01307   Expr t1, t2;
01308   Rational c1, c2;
01309   int num_vars = extractTermsFromInequality(ineq, c1, t1, c2, t2);
01310 
01311   // If 2 variable, do add to difference logic (allways, just in case)
01312   bool factIsDiffLogic = false;
01313   if (num_vars <= 2) {
01314 
01315     TRACE("arith diff", t2, " < ", c2);
01316       // c1 <= t1, check if difference logic
01317       // t1 of the form 0 + ax + by
01318       Expr ax = (num_vars == 2 ? t2[1] : t2);
01319       Expr a_expr, x;
01320       separateMonomial(ax, a_expr, x);
01321       Rational a = a_expr.getRational();
01322       Expr by = (num_vars == 2 ? t2[2] : (a < 0 ? zero : rat(-1)*zero));
01323       Expr b_expr, y;
01324       separateMonomial(by, b_expr, y);
01325       Rational b = b_expr.getRational();
01326 
01327       // Check for non-linear
01328       if (!isLeaf(x) || !isLeaf(y))
01329         setIncomplete("Non-linear arithmetic inequalities");
01330 
01331       if (a == 1 && b == -1) {
01332         diffLogicGraph.addEdge(x, y, c2, thm);
01333         factIsDiffLogic = true;
01334       }
01335       else if (a == -1 && b == 1) {
01336         diffLogicGraph.addEdge(y, x, c2, thm);
01337         factIsDiffLogic = true;
01338       }
01339       // Not difference logic, put it in the 3 or more vars buffer
01340       else {
01341         diffLogicOnly = false;
01342         TRACE("arith diff", "not diff logic", thm.getExpr().toString(), "");
01343       }
01344 
01345       if (diffLogicGraph.isUnsat()) {
01346         TRACE("diff unsat", "UNSAT", " : ", diffLogicGraph.getUnsatTheorem());
01347         setInconsistent(diffLogicGraph.getUnsatTheorem());
01348         return false;
01349       }
01350   } else {
01351     diffLogicOnly = false;
01352     TRACE("arith diff", "not diff logic", thm.getExpr().toString(), "");
01353   }
01354 
01355   // For now we treat all the bound as LE, weaker
01356   CDMap<Expr, Rational>::iterator find_lower = termLowerBound.find(t1);
01357   if (find_lower != termLowerBound.end()) {
01358     // found bound c <= t1
01359     Rational found_c = (*find_lower).second;
01360     // If found c is bigger than the new one, we are done
01361     if (c1 <= found_c && !(found_c == c1 && ineq.getKind() == LT)) {
01362       TRACE("arith buffer", "addToBuffer()", "", "... lower_bound subsumed");
01363       // Removed assert. Can happen that an atom is not asserted yet, and get's implied as
01364       // a formula atom and then asserted here. it's fine
01365       //DebugAssert(!thm.isAssump(), "Should have been propagated: " + ineq.toString() + "");
01366       return false;
01367     } else {
01368       Theorem oldLowerBound = termLowerBoundThm[t1];
01369       Expr oldIneq = oldLowerBound.getExpr();
01370       if (formulaAtoms.find(oldIneq) != formulaAtoms.end())
01371         enqueueFact(getCommonRules()->implMP(thm, d_rules->implyWeakerInequality(ineq, oldIneq)));
01372       termLowerBound[t1] = c1;
01373       termLowerBoundThm[t1] = thm;
01374     }
01375   } else {
01376     termLowerBound[t1] = c1;
01377     termLowerBoundThm[t1] = thm;
01378   }
01379 
01380   CDMap<Expr, Rational>::iterator find_upper = termUpperBound.find(t2);
01381   if (find_upper != termUpperBound.end()) {
01382     // found bound t2 <= c
01383     Rational found_c = (*find_upper).second;
01384     // If found c is smaller than the new one, we are done
01385     if (found_c <= c2 && !(found_c == c2 && ineq.getKind() == LT)) {
01386       TRACE("arith buffer", "addToBuffer()", "", "... upper_bound subsumed");
01387       //DebugAssert(!thm.isAssump(), "Should have been propagated: " + ineq.toString() + "");
01388       return false;
01389     } else {
01390       termUpperBound[t2] = c2;
01391       termUpperBoundThm[t2] = thm;
01392     }
01393   } else {
01394     termUpperBound[t2] = c2;
01395     termUpperBoundThm[t2] = thm;
01396   }
01397 
01398   // See if the bounds on the term can infer conflict or equality
01399   if (termUpperBound.find(t1) != termUpperBound.end() &&
01400       termLowerBound.find(t1) != termLowerBound.end() &&
01401       termUpperBound[t1] <= termLowerBound[t1]) {
01402     Theorem thm1 = termUpperBoundThm[t1];
01403     Theorem thm2 = termLowerBoundThm[t1];
01404     TRACE("arith propagate", "adding inequalities: ", thm1.getExpr().toString(), " with " + thm2.getExpr().toString());
01405     enqueueFact(d_rules->addInequalities(thm1, thm2));
01406   } else
01407   if (termUpperBound.find(t2) != termUpperBound.end() &&
01408         termLowerBound.find(t2) != termLowerBound.end() &&
01409         termUpperBound[t2] <= termLowerBound[t2]) {
01410     Theorem thm1 = termUpperBoundThm[t2];
01411     Theorem thm2 = termLowerBoundThm[t2];
01412     TRACE("arith propagate", "adding inequalities: ", thm1.getExpr().toString(), " with " + thm2.getExpr().toString());
01413       enqueueFact(d_rules->addInequalities(thm1, thm2));
01414   }
01415 
01416   if (true) {
01417     // See if we can propagate anything to the formula atoms
01418     // c1 <= t1 ===> c <= t1 for c < c1
01419     AtomsMap::iterator find     = formulaAtomLowerBound.find(t1);
01420     AtomsMap::iterator find_end = formulaAtomLowerBound.end();
01421     if (find != find_end) {
01422         set< pair<Rational, Expr> >::iterator bounds     = (*find).second.begin();
01423         set< pair<Rational, Expr> >::iterator bounds_end = (*find).second.end();
01424         while (bounds != bounds_end) {
01425           TRACE("arith atoms", "trying propagation", ineq, (*bounds).second);
01426           const Expr& implied = (*bounds).second;
01427           // Try to do some theory propagation
01428           if ((*bounds).first < c1 || (!(ineq.getKind() == LE && implied.getKind() == LT) && (*bounds).first == c1)) {
01429             // c1 <= t1 => c <= t1 (for c <= c1)
01430             // c1 < t1  => c <= t1 (for c <= c1)
01431             // c1 <= t1 => c < t1  (for c < c1)
01432             Theorem impliedThm = getCommonRules()->implMP(thm, d_rules->implyWeakerInequality(ineq, implied));
01433             enqueueFact(impliedThm);
01434           }
01435           bounds ++;
01436         }
01437     }
01438 
01439     //
01440     // c1 <= t1 ==> !(t1 <= c) for c < c1
01441     //          ==> !(-c <= t2)
01442     // i.e. all coefficient in in the implied are opposite of t1
01443     find     = formulaAtomUpperBound.find(t1);
01444     find_end = formulaAtomUpperBound.end();
01445     if (find != find_end) {
01446         set< pair<Rational, Expr> >::iterator bounds     = (*find).second.begin();
01447         set< pair<Rational, Expr> >::iterator bounds_end = (*find).second.end();
01448         while (bounds != bounds_end) {
01449           TRACE("arith atoms", "trying propagation", ineq, (*bounds).second);
01450           const Expr& implied = (*bounds).second;
01451           // Try to do some theory propagation
01452           if ((*bounds).first < c1) {
01453             Theorem impliedThm = getCommonRules()->implMP(thm, d_rules->implyNegatedInequality(ineq, implied));
01454             enqueueFact(impliedThm);
01455           }
01456           bounds ++;
01457         }
01458     }
01459   }
01460 
01461   // Register this as a resource
01462   theoryCore()->getResource();
01463 
01464   // If out of resources, bail out
01465   if (theoryCore()->outOfResources()) return false;
01466 
01467   // Checking because we could have projected it as a find of some other
01468   // equation
01469   if (alreadyProjected.find(ineq) == alreadyProjected.end()) {
01470     // We buffer it if it's not marked for not buffering
01471     if (dontBuffer.find(ineq) == dontBuffer.end()) {
01472       // We give priority to the one that can produce a conflict
01473       if (priority)
01474         d_buffer_0.push_back(thm);
01475       else {
01476         // Push it into the buffer (one var)
01477         if (num_vars == 1) d_buffer_1.push_back(thm);
01478         else if (num_vars == 2) d_buffer_2.push_back(thm);
01479         else d_buffer_3.push_back(thm);
01480       }
01481 
01482       if (factIsDiffLogic) diff_logic_size = diff_logic_size + 1;
01483     }
01484   }
01485 
01486   // Remember that it's in the buffer
01487   bufferedInequalities[ineq] = thm;
01488 
01489   // Since we care about this atom, lets set it up
01490   if (!ineq.hasFind())
01491     theoryCore()->setupTerm(ineq, this, thm);
01492 
01493   return true;
01494 }
01495 
01496 
01497 Theorem TheoryArithOld::isolateVariable(const Theorem& inputThm,
01498                                      bool& isolatedVarOnRHS)
01499 {
01500   Theorem result(inputThm);
01501   const Expr& e = inputThm.getExpr();
01502   TRACE("arith","isolateVariable(",e,") {");
01503   TRACE("arith ineq", "isolateVariable(", e, ") {");
01504   //we assume all the children of e are canonized
01505   DebugAssert(isLT(e)||isLE(e),
01506               "TheoryArithOld::isolateVariable: " + e.toString() +
01507               " wrong kind");
01508   int kind = e.getKind();
01509   DebugAssert(e[0].isRational() && e[0].getRational() == 0,
01510               "TheoryArithOld::isolateVariable: theorem must be of "
01511               "the form 0 < rhs: " + inputThm.toString());
01512 
01513   const Expr& zero = e[0];
01514   Expr right = e[1];
01515   // Check for trivial in-equation.
01516   if (right.isRational()) {
01517     result = iffMP(result, d_rules->constPredicate(e));
01518     TRACE("arith ineq","isolateVariable => ",result.getExpr()," }");
01519     TRACE("arith","isolateVariable => ",result," }");
01520     return result;
01521   }
01522 
01523   // Normalization of inequality to make coefficients integer and
01524   // relatively prime.
01525 
01526   Expr factor(computeNormalFactor(right, false));
01527   TRACE("arith", "isolateVariable: factor = ", factor, "");
01528   DebugAssert(factor.getRational() > 0,
01529               "isolateVariable: factor="+factor.toString());
01530   // Now multiply the inequality by the factor, unless it is 1
01531   if(factor.getRational() != 1) {
01532     result = iffMP(result, d_rules->multIneqn(e, factor));
01533     // And canonize the result
01534     result = canonPred(result);
01535     result = rafineInequalityToInteger(result);
01536     right = result.getExpr()[1];
01537   }
01538 
01539   // Find monomial to isolate and store it in isolatedMonomial
01540   Expr isolatedMonomial = right;
01541 
01542   if (isPlus(right))
01543     isolatedMonomial = pickMonomial(right);
01544 
01545   TRACE("arith ineq", "isolatedMonomial => ",isolatedMonomial,"");
01546 
01547   // Set the correct isolated monomial
01548   // Now, if something gets updated, but this monomial is not changed, we don't
01549   // Have to rebuffer it as the projection will still be accurate when updated
01550   alreadyProjected[e] = isolatedMonomial;
01551 
01552   Rational r = -1;
01553   isolatedVarOnRHS = true;
01554   if (isMult(isolatedMonomial)) {
01555     r = ((isolatedMonomial[0].getRational()) >= 0)? -1 : 1;
01556     isolatedVarOnRHS =
01557       ((isolatedMonomial[0].getRational()) >= 0)? true : false;
01558   }
01559   isolatedMonomial = canon(rat(-1)*isolatedMonomial).getRHS();
01560   TRACE("arith ineq", "-(isolatedMonomial) => ",isolatedMonomial,"");
01561     // Isolate isolatedMonomial on to the LHS
01562   result = iffMP(result, d_rules->plusPredicate(zero, right,
01563                                                 isolatedMonomial, kind));
01564   // Canonize the resulting inequality
01565   TRACE("arith ineq", "resutl => ",result,"");
01566     result = canonPred(result);
01567   if(1 != r) {
01568     result = iffMP(result, d_rules->multIneqn(result.getExpr(), rat(r)));
01569     result = canonPred(result);
01570   }
01571   TRACE("arith ineq","isolateVariable => ",result.getExpr()," }");
01572   TRACE("arith","isolateVariable => ",result," }");
01573   return result;
01574 }
01575 
01576 Expr
01577 TheoryArithOld::computeNormalFactor(const Expr& right, bool normalizeConstants) {
01578   // Strategy: compute f = lcm(d1...dn)/gcd(c1...cn), where the RHS is
01579   // of the form c1/d1*x1 + ... + cn/dn*xn
01580   Rational factor;
01581   if(isPlus(right)) {
01582     vector<Rational> nums, denoms;
01583     for(int i=0, iend=right.arity(); i<iend; ++i) {
01584       switch(right[i].getKind()) {
01585       case RATIONAL_EXPR:
01586       if (normalizeConstants)  {
01587         Rational c(abs(right[i].getRational()));
01588         nums.push_back(c.getNumerator());
01589         denoms.push_back(c.getDenominator());
01590         break;
01591         }
01592         break;
01593       case MULT: {
01594         Rational c(abs(right[i][0].getRational()));
01595         nums.push_back(c.getNumerator());
01596         denoms.push_back(c.getDenominator());
01597         break;
01598         }
01599       default: // it's a variable
01600         nums.push_back(1);
01601         denoms.push_back(1);
01602         break;
01603       }
01604     }
01605     Rational gcd_nums = gcd(nums);
01606     // x/0 == 0 in our model, as a total extension of arithmetic.  The
01607     // particular value of x/0 is irrelevant, since the DP is guarded
01608     // by the top-level TCCs, and it is safe to return any value in
01609     // cases when terms are undefined.
01610     factor = (gcd_nums==0)? 0 : (lcm(denoms) / gcd_nums);
01611   } else if(isMult(right)) {
01612     const Rational& r = right[0].getRational();
01613     factor = (r==0)? 0 : (1/abs(r));
01614   }
01615   else
01616     factor = 1;
01617   return rat(factor);
01618 }
01619 
01620 
01621 bool TheoryArithOld::lessThanVar(const Expr& isolatedMonomial, const Expr& var2)
01622 {
01623   DebugAssert(!isRational(var2) && !isRational(isolatedMonomial),
01624               "TheoryArithOld::findMaxVar: isolatedMonomial cannot be rational" +
01625               isolatedMonomial.toString());
01626   Expr c, var0, var1;
01627   separateMonomial(isolatedMonomial, c, var0);
01628   separateMonomial(var2, c, var1);
01629   return var0 < var1;
01630 }
01631 
01632 /*! "Stale" means it contains non-simplified subexpressions.  For
01633  *  terms, it checks the expression's find pointer; for formulas it
01634  *  checks the children recursively (no caching!).  So, apply it with
01635  *  caution, and only to simple atomic formulas (like inequality).
01636  */
01637 bool TheoryArithOld::isStale(const Expr& e) {
01638   if(e.isTerm())
01639     return e != find(e).getRHS();
01640   // It's better be a simple predicate (like inequality); we check the
01641   // kids recursively
01642   bool stale=false;
01643   for(Expr::iterator i=e.begin(), iend=e.end(); !stale && i!=iend; ++i)
01644     stale = isStale(*i);
01645   return stale;
01646 }
01647 
01648 
01649 bool TheoryArithOld::isStale(const TheoryArithOld::Ineq& ineq) {
01650   TRACE("arith stale", "isStale(", ineq, ") {");
01651   const Expr& ineqExpr = ineq.ineq().getExpr();
01652   const Rational& c = freeConstIneq(ineqExpr, ineq.varOnRHS());
01653   bool strict(isLT(ineqExpr));
01654   const FreeConst& fc = ineq.getConst();
01655 
01656   bool subsumed;
01657 
01658   if (ineqExpr.hasFind() && find(ineqExpr[1]).getRHS() != ineqExpr[1])
01659     return true;
01660 
01661   if(ineq.varOnRHS()) {
01662     subsumed = (c < fc.getConst() ||
01663     (c == fc.getConst() && !strict && fc.strict()));
01664   } else {
01665     subsumed = (c > fc.getConst() ||
01666     (c == fc.getConst() && strict && !fc.strict()));
01667   }
01668 
01669   bool res;
01670   if(subsumed) {
01671     res = true;
01672     TRACE("arith ineq", "isStale[subsumed] => ", res? "true" : "false", " }");
01673   }
01674   else {
01675     res = isStale(ineqExpr);
01676     TRACE("arith ineq", "isStale[updated] => ", res? "true" : "false", " }");
01677   }
01678   return res;
01679 }
01680 
01681 
01682 void TheoryArithOld::separateMonomial(const Expr& e, Expr& c, Expr& var) {
01683   TRACE("separateMonomial", "separateMonomial(", e, ")");
01684   DebugAssert(!isPlus(e),
01685         "TheoryArithOld::separateMonomial(e = "+e.toString()+")");
01686   if(isMult(e)) {
01687     DebugAssert(e.arity() >= 2,
01688     "TheoryArithOld::separateMonomial(e = "+e.toString()+")");
01689     c = e[0];
01690     if(e.arity() == 2) var = e[1];
01691     else {
01692       vector<Expr> kids = e.getKids();
01693       kids[0] = rat(1);
01694       var = multExpr(kids);
01695     }
01696   } else {
01697     c = rat(1);
01698     var = e;
01699   }
01700   DebugAssert(c.isRational(), "TheoryArithOld::separateMonomial(e = "
01701         +e.toString()+", c = "+c.toString()+")");
01702   DebugAssert(!isMult(var) || (var[0].isRational() && var[0].getRational()==1),
01703         "TheoryArithOld::separateMonomial(e = "
01704         +e.toString()+", var = "+var.toString()+")");
01705 }
01706 
01707 
01708 void TheoryArithOld::projectInequalities(const Theorem& theInequality,
01709                                       bool isolatedVarOnRHS)
01710 {
01711 
01712   TRACE("arith project", "projectInequalities(", theInequality.getExpr(),
01713         ", isolatedVarOnRHS="+string(isolatedVarOnRHS? "true" : "false")
01714         +") {");
01715   DebugAssert(isLE(theInequality.getExpr()) ||
01716               isLT(theInequality.getExpr()),
01717               "TheoryArithOld::projectIsolatedVar: "\
01718               "theInequality is of the wrong form: " +
01719               theInequality.toString());
01720 
01721   //TODO: DebugAssert to check if the isolatedMonomial is of the right
01722   //form and the whether we are indeed getting inequalities.
01723   Theorem theIneqThm(theInequality);
01724   Expr theIneq = theIneqThm.getExpr();
01725 
01726   // If the inequality is strict and integer, change it to non-strict
01727   if(isLT(theIneq)) {
01728     Theorem isIntLHS(isIntegerThm(theIneq[0]));
01729     Theorem isIntRHS(isIntegerThm(theIneq[1]));
01730     if ((!isIntLHS.isNull() && !isIntRHS.isNull())) {
01731       Theorem thm = d_rules->lessThanToLE(theInequality, isIntLHS, isIntRHS, !isolatedVarOnRHS);
01732       theIneqThm = canonPred(iffMP(theIneqThm, thm));
01733       theIneq = theIneqThm.getExpr();
01734     }
01735   }
01736 
01737   Expr isolatedMonomial = isolatedVarOnRHS ? theIneq[1] : theIneq[0];
01738 
01739   Expr monomialVar, a;
01740   separateMonomial(isolatedMonomial, a, monomialVar);
01741 
01742   bool subsumed;
01743   const FreeConst& bestConst = updateSubsumptionDB(theIneq, isolatedVarOnRHS, subsumed);
01744 
01745   if(subsumed) {
01746     IF_DEBUG(debugger.counter("subsumed inequalities")++;)
01747     TRACE("arith ineq", "subsumed inequality: ", theIneq, "");
01748   } else {
01749     // If the isolated variable is actually a non-linear term, we are
01750     // incomplete
01751     if(isMult(monomialVar) || isPow(monomialVar))
01752       setIncomplete("Non-linear arithmetic inequalities");
01753 
01754     // First, we need to make sure the isolated inequality is
01755     // setup properly.
01756     //    setupRec(theIneq[0]);
01757     //    setupRec(theIneq[1]);
01758     theoryCore()->setupTerm(theIneq[0], this, theIneqThm);
01759     theoryCore()->setupTerm(theIneq[1], this, theIneqThm);
01760     // Add the inequality into the appropriate DB.
01761     ExprMap<CDList<Ineq> *>& db1 = isolatedVarOnRHS ? d_inequalitiesRightDB : d_inequalitiesLeftDB;
01762     ExprMap<CDList<Ineq> *>::iterator it1 = db1.find(monomialVar);
01763     if(it1 == db1.end()) {
01764       CDList<Ineq> * list = new(true) CDList<Ineq>(theoryCore()->getCM()->getCurrentContext());
01765       list->push_back(Ineq(theIneqThm, isolatedVarOnRHS, bestConst));
01766       db1[monomialVar] = list;
01767     }
01768     else
01769       ((*it1).second)->push_back(Ineq(theIneqThm, isolatedVarOnRHS, bestConst));
01770 
01771     ExprMap<CDList<Ineq> *>& db2 = isolatedVarOnRHS ? d_inequalitiesLeftDB : d_inequalitiesRightDB;
01772     ExprMap<CDList<Ineq> *>::iterator it = db2.find(monomialVar);
01773     if(it == db2.end()) {
01774       TRACE_MSG("arith ineq", "projectInequalities[not in DB] => }");
01775       return;
01776     }
01777 
01778     CDList<Ineq>& listOfDBIneqs = *((*it).second);
01779     Theorem betaLTt, tLTalpha, thm;
01780     for(int i = listOfDBIneqs.size() - 1; !inconsistent() && i >= 0; --i) {
01781       const Ineq& ineqEntry = listOfDBIneqs[i];
01782       const Theorem& ineqThm = ineqEntry.ineq(); //inequalityToFind(ineqEntry.ineq(), isolatedVarOnRHS);
01783 
01784       // ineqExntry might be stale
01785 
01786       if(!isStale(ineqEntry)) {
01787         betaLTt = isolatedVarOnRHS ? theIneqThm : ineqThm;
01788         tLTalpha = isolatedVarOnRHS ? ineqThm : theIneqThm;
01789 
01790         thm = normalizeProjectIneqs(betaLTt, tLTalpha);
01791         if (thm.isNull()) continue;
01792 
01793         IF_DEBUG(debugger.counter("real shadows")++;)
01794 
01795         // Check for TRUE and FALSE theorems
01796         Expr e(thm.getExpr());
01797 
01798         if(e.isFalse()) {
01799           setInconsistent(thm);
01800           TRACE_MSG("arith ineq", "projectInequalities[inconsistent] => }");
01801           return;
01802         }
01803         else {
01804           if(!e.isTrue() && !e.isEq()) {
01805             // setup the term so that it comes out in updates
01806             addToBuffer(thm, false);
01807           }
01808           else if(e.isEq())
01809             enqueueFact(thm);
01810         }
01811       } else {
01812         IF_DEBUG(debugger.counter("stale inequalities")++;)
01813       }
01814     }
01815   }
01816 
01817   TRACE_MSG("arith ineq", "projectInequalities => }");
01818 }
01819 
01820 Theorem TheoryArithOld::normalizeProjectIneqs(const Theorem& ineqThm1,
01821                                            const Theorem& ineqThm2)
01822 {
01823   //ineq1 is of the form beta < b.x  or beta < x  [ or with <= ]
01824   //ineq2 is of the form a.x < alpha   or x < alpha.
01825   Theorem betaLTt = ineqThm1, tLTalpha = ineqThm2;
01826   Expr ineq1 = betaLTt.getExpr();
01827   Expr ineq2 = tLTalpha.getExpr();
01828   Expr c,x;
01829   separateMonomial(ineq2[0], c, x);
01830   Theorem isIntx(isIntegerThm(x));
01831   Theorem isIntBeta(isIntegerThm(ineq1[0]));
01832   Theorem isIntAlpha(isIntegerThm(ineq2[1]));
01833   bool isInt = !(isIntx.isNull() || isIntBeta.isNull() || isIntAlpha.isNull());
01834 
01835   TRACE("arith ineq", "normalizeProjectIneqs(", ineq1,
01836         ", "+ineq2.toString()+") {");
01837   DebugAssert((isLE(ineq1) || isLT(ineq1)) &&
01838               (isLE(ineq2) || isLT(ineq2)),
01839               "TheoryArithOld::normalizeProjectIneqs: Wrong Kind inputs: " +
01840               ineq1.toString() + ineq2.toString());
01841   DebugAssert(!isPlus(ineq1[1]) && !isPlus(ineq2[0]),
01842               "TheoryArithOld::normalizeProjectIneqs: Wrong Kind inputs: " +
01843               ineq1.toString() + ineq2.toString());
01844 
01845   //compute the factors to multiply the two inequalities with
01846   //so that they get the form beta < t and t < alpha.
01847   Rational factor1 = 1, factor2 = 1;
01848   Rational b = isMult(ineq1[1]) ? (ineq1[1])[0].getRational() : 1;
01849   Rational a = isMult(ineq2[0]) ? (ineq2[0])[0].getRational() : 1;
01850   if(b != a) {
01851     factor1 = a;
01852     factor2 = b;
01853   }
01854 
01855   //if the ineqs are of type int then apply one of the gray
01856   //dark shadow rules.
01857   // FIXME: intResult should also be checked for immediate
01858   // optimizations, as those below for 'result'.  Also, if intResult
01859   // is a single inequality, we may want to handle it similarly to the
01860   // 'result' rather than enqueuing directly.
01861   if(isInt && (a >= 2 || b >= 2)) {
01862     Theorem intResult;
01863     if(a <= b)
01864       intResult = d_rules->darkGrayShadow2ab(betaLTt, tLTalpha,
01865                isIntAlpha, isIntBeta, isIntx);
01866     else
01867       intResult = d_rules->darkGrayShadow2ba(betaLTt, tLTalpha,
01868                isIntAlpha, isIntBeta, isIntx);
01869   enqueueFact(intResult);
01870     // Fetch dark and gray shadows
01871     const Expr& DorG = intResult.getExpr();
01872     DebugAssert(DorG.isOr() && DorG.arity()==2, "DorG = "+DorG.toString());
01873     const Expr& G = DorG[1];
01874     DebugAssert(G.getKind()==GRAY_SHADOW, "G = "+G.toString());
01875     // Set the higher splitter priority for dark shadow
01876 //    Expr tmp = simplifyExpr(D);
01877 //    if (!tmp.isBoolConst())
01878 //      addSplitter(tmp, 5);
01879     // Also set a higher priority to the NEGATION of GRAY_SHADOW
01880     Expr tmp = simplifyExpr(!G);
01881     if (!tmp.isBoolConst())
01882       addSplitter(tmp, 1);
01883     IF_DEBUG(debugger.counter("dark+gray shadows")++;)
01884 
01885     // Dejan: Let's forget about the real shadow, we are doing integers
01886 //    /return intResult;
01887   }
01888 
01889   //actually normalize the inequalities
01890   if(1 != factor1) {
01891     Theorem thm2 = iffMP(betaLTt, d_rules->multIneqn(ineq1, rat(factor1)));
01892     betaLTt = canonPred(thm2);
01893     ineq1 = betaLTt.getExpr();
01894   }
01895   if(1 != factor2) {
01896     Theorem thm2 = iffMP(tLTalpha, d_rules->multIneqn(ineq2, rat(factor2)));
01897     tLTalpha = canonPred(thm2);
01898     ineq2 = tLTalpha.getExpr();
01899   }
01900 
01901   //IF_DEBUG(debugger.counter("real shadows")++;)
01902 
01903   Expr beta(ineq1[0]);
01904   Expr alpha(ineq2[1]);
01905   // In case of alpha <= t <= alpha, we generate t = alpha
01906   if(isLE(ineq1) && isLE(ineq2) && alpha == beta) {
01907     Theorem result = d_rules->realShadowEq(betaLTt, tLTalpha);
01908     TRACE("arith ineq", "normalizeProjectIneqs => ", result, " }");
01909     return result;
01910   }
01911 
01912   // Check if this inequality is a finite interval
01913 //  if(isInt)
01914 //    processFiniteInterval(betaLTt, tLTalpha);
01915 
01916 //  // Only do the real shadow if a and b = 1
01917 //  if (isInt && a > 1 && b > 1)
01918 //    return Theorem();
01919 
01920   //project the normalized inequalities.
01921 
01922   Theorem result = d_rules->realShadow(betaLTt, tLTalpha);
01923 
01924   // FIXME: Clark's changes.  Is 'rewrite' more or less efficient?
01925 //   result = iffMP(result, rewrite(result.getExpr()));
01926 //   TRACE("arith ineq", "normalizeProjectIneqs => ", result, " }");
01927 
01928   // Now, transform the result into 0 < rhs and see if rhs is a const
01929   Expr e(result.getExpr());
01930   // int kind = e.getKind();
01931   if(!(e[0].isRational() && e[0].getRational() == 0))
01932     result = iffMP(result, d_rules->rightMinusLeft(e));
01933   result = canonPred(result);
01934 
01935   //result is "0 kind e'". where e' is equal to canon(e[1]-e[0])
01936   Expr right = result.getExpr()[1];
01937   // Check for trivial inequality
01938   if (right.isRational())
01939     result = iffMP(result, d_rules->constPredicate(result.getExpr()));
01940   else
01941   result = normalize(result);
01942   TRACE("arith ineq", "normalizeProjectIneqs => ", result, " }");
01943   return result;
01944 }
01945 
01946 Rational TheoryArithOld::currentMaxCoefficient(Expr var)
01947 {
01948   // We prefer real variables
01949   if (var.getType() == d_realType) return -100;
01950 
01951   // Find the biggest left side coefficient
01952   ExprMap<Rational>::iterator findMaxLeft = maxCoefficientLeft.find(var);
01953   Rational leftMax = -1;
01954   if (findMaxLeft != maxCoefficientLeft.end())
01955     leftMax = (*findMaxLeft).second;
01956 
01957   //
01958   ExprMap<Rational>::iterator findMaxRight = maxCoefficientRight.find(var);
01959   Rational rightMax = -1;
01960   if (findMaxRight != maxCoefficientRight.end())
01961     rightMax = (*findMaxRight).second;
01962 
01963   // What is the max coefficient
01964   // If one is undefined, dont take it. My first thought was to project away unbounded
01965   // ones, but it happens that you get another constraint on it later and the hell breaks
01966   // loose if they have big coefficients.
01967   Rational returnValue;
01968   if (leftMax == -1) returnValue = rightMax;
01969   else if (rightMax == -1) returnValue = leftMax;
01970   else if (leftMax < rightMax) returnValue = rightMax;
01971   else returnValue = leftMax;
01972 
01973   TRACE("arith stats", "max coeff of ", var.toString(), ": " + returnValue.toString() + "(left=" + leftMax.toString() + ",right=" + rightMax.toString());
01974 
01975   return returnValue;
01976 }
01977 
01978 void TheoryArithOld::fixCurrentMaxCoefficient(Expr var, Rational max) {
01979   fixedMaxCoefficient[var] = max;
01980 }
01981 
01982 void TheoryArithOld::selectSmallestByCoefficient(const vector<Expr>& input, vector<Expr>& output) {
01983 
01984   // Clear the output vector
01985   output.clear();
01986 
01987   // Get the first variable, and set it as best
01988   Expr best_variable = input[0];
01989   Rational best_coefficient = currentMaxCoefficient(best_variable);
01990   output.push_back(best_variable);
01991 
01992   for(unsigned int i = 1; i < input.size(); i ++) {
01993 
01994     // Get the current variable
01995     Expr current_variable = input[i];
01996     // Get the current variable's max coefficient
01997     Rational current_coefficient = currentMaxCoefficient(current_variable);
01998 
01999     // If strictly better than the current best, remember it
02000     if ((current_coefficient < best_coefficient)) {
02001       best_variable = current_variable;
02002       best_coefficient = current_coefficient;
02003       output.clear();
02004     }
02005 
02006     // If equal to the current best, push it to the stack (in 10% range)
02007     if (current_coefficient == best_coefficient)
02008         output.push_back(current_variable);
02009   }
02010 
02011     // Fix the selected best coefficient
02012   //fixCurrentMaxCoefficient(best_variable, best_coefficient);
02013 }
02014 
02015 Expr TheoryArithOld::pickMonomial(const Expr& right)
02016 {
02017   DebugAssert(isPlus(right), "TheoryArithOld::pickMonomial: Wrong Kind: " +
02018               right.toString());
02019   if(theoryCore()->getFlags()["var-order"].getBool()) {
02020     Expr::iterator i = right.begin();
02021     Expr isolatedMonomial = right[1];
02022     //PLUS always has at least two elements and the first element is
02023     //always a constant. hence ++i in the initialization of the for
02024     //loop.
02025     for(++i; i != right.end(); ++i)
02026       if(lessThanVar(isolatedMonomial,*i))
02027         isolatedMonomial = *i;
02028     return isolatedMonomial;
02029   }
02030 
02031   ExprMap<Expr> var2monomial;
02032   vector<Expr> vars;
02033   Expr::iterator i = right.begin(), iend = right.end();
02034   for(;i != iend; ++i) {
02035     if(i->isRational())
02036       continue;
02037     Expr c, var;
02038     separateMonomial(*i, c, var);
02039     var2monomial[var] = *i;
02040     vars.push_back(var);
02041   }
02042 
02043   vector<Expr> largest;
02044   d_graph.selectLargest(vars, largest);
02045   DebugAssert(0 < largest.size(),
02046               "TheoryArithOld::pickMonomial: selectLargest: failed!!!!");
02047 
02048   // DEJAN: Rafine the largest by coefficient values
02049   vector<Expr> largest_small_coeff;
02050   selectSmallestByCoefficient(largest, largest_small_coeff);
02051   DebugAssert(0 < largest_small_coeff.size(), "TheoryArithOld::pickMonomial: selectLargestByCOefficient: failed!!!!");
02052 
02053   size_t pickedVar = 0;
02054     // Pick the variable which will generate the fewest number of
02055     // projections
02056 
02057   size_t size = largest_small_coeff.size();
02058   int minProjections = -1;
02059   if (size > 1)
02060   for(size_t k=0; k< size; ++k) {
02061       const Expr& var(largest_small_coeff[k]), monom(var2monomial[var]);
02062       // Grab the counters for the variable
02063       int nRight = (d_countRight.count(var) > 0)? d_countRight[var] : 0;
02064       int nLeft = (d_countLeft.count(var) > 0)? d_countLeft[var] : 0;
02065       int n(nRight*nLeft);
02066       TRACE("arith ineq", "pickMonomial: var=", var,
02067             ", nRight="+int2string(nRight)+", nLeft="+int2string(nLeft));
02068       if(minProjections < 0 || minProjections > n) {
02069         minProjections = n;
02070         pickedVar = k;
02071       }
02072       TRACE("arith ineq", "Number of projections for "+var.toString()+" = ", n, "");
02073   }
02074 
02075 
02076   const Expr& largestVar = largest_small_coeff[pickedVar];
02077   // FIXME: TODO: update the counters (subtract counts for the vars
02078   // other than largestVar
02079 
02080   // Update the graph (all edges to the largest in the graph, not just the small coefficients).
02081   for(size_t k = 0; k < vars.size(); ++k) {
02082     if(vars[k] != largestVar)
02083       d_graph.addEdge(largestVar, vars[k]);
02084   }
02085 
02086   TRACE("arith buffer", "picked var : ", var2monomial[largestVar].toString(), "");
02087 
02088   return var2monomial[largestVar];
02089 }
02090 
02091 void TheoryArithOld::VarOrderGraph::addEdge(const Expr& e1, const Expr& e2)
02092 {
02093   TRACE("arith var order", "addEdge("+e1.toString()+" > ", e2, ")");
02094   DebugAssert(e1 != e2, "TheoryArithOld::VarOrderGraph::addEdge("
02095         +e1.toString()+", "+e2.toString()+")");
02096   d_edges[e1].push_back(e2);
02097 }
02098 
02099 //returns true if e1 < e2, else false(i.e e2 < e1 or e1,e2 are not
02100 //comparable)
02101 bool TheoryArithOld::VarOrderGraph::lessThan(const Expr& e1, const Expr& e2)
02102 {
02103   d_cache.clear();
02104   //returns true if e1 is in the subtree rooted at e2 implying e1 < e2
02105   return dfs(e1,e2);
02106 }
02107 
02108 //returns true if e1 is in the subtree rooted at e2 implying e1 < e2
02109 bool TheoryArithOld::VarOrderGraph::dfs(const Expr& e1, const Expr& e2)
02110 {
02111   if(e1 == e2)
02112     return true;
02113   if(d_cache.count(e2) > 0)
02114     return false;
02115   if(d_edges.count(e2) == 0)
02116     return false;
02117   d_cache[e2] = true;
02118   vector<Expr>& e2Edges = d_edges[e2];
02119   vector<Expr>::iterator i = e2Edges.begin();
02120   vector<Expr>::iterator iend = e2Edges.end();
02121   //if dfs finds e1 then i != iend else i is equal to iend
02122   for(; i != iend && !dfs(e1,*i); ++i);
02123   return (i != iend);
02124 }
02125 
02126 void TheoryArithOld::VarOrderGraph::dfs(const Expr& v, vector<Expr>& output_list)
02127 {
02128   TRACE("arith shared", "dfs(", v.toString(), ")");
02129 
02130   // If visited already we are done
02131   if (d_cache.count(v) > 0) return;
02132 
02133   // Dfs further
02134   if(d_edges.count(v) != 0) {
02135     // We have edges, so lets dfs it further
02136     vector<Expr>& vEdges = d_edges[v];
02137     vector<Expr>::iterator e = vEdges.begin();
02138     vector<Expr>::iterator e_end = vEdges.end();
02139     while (e != e_end) {
02140       dfs(*e, output_list);
02141       e ++;
02142     }
02143   }
02144 
02145   // Mark as visited and add to the output list
02146   d_cache[v] = true;
02147   output_list.push_back(v);
02148 }
02149 
02150 void TheoryArithOld::VarOrderGraph::getVerticesTopological(vector<Expr>& output_list)
02151 {
02152   // Clear the cache
02153   d_cache.clear();
02154   output_list.clear();
02155 
02156   // Go through all the vertices and run a dfs from them
02157   ExprMap< vector<Expr> >::iterator v_it     = d_edges.begin();
02158   ExprMap< vector<Expr> >::iterator v_it_end = d_edges.end();
02159   while (v_it != v_it_end)
02160   {
02161     // Run dfs from this vertex
02162     dfs(v_it->first, output_list);
02163     // Go to the next one
02164     v_it ++;
02165   }
02166 }
02167 
02168 void TheoryArithOld::VarOrderGraph::selectSmallest(vector<Expr>& v1,
02169                                                vector<Expr>& v2)
02170 {
02171   int v1Size = v1.size();
02172   vector<bool> v3(v1Size);
02173   for(int j=0; j < v1Size; ++j)
02174     v3[j] = false;
02175 
02176   for(int j=0; j < v1Size; ++j) {
02177     if(v3[j]) continue;
02178     for(int i =0; i < v1Size; ++i) {
02179       if((i == j) || v3[i])
02180         continue;
02181       if(lessThan(v1[i],v1[j])) {
02182         v3[j] = true;
02183         break;
02184       }
02185     }
02186   }
02187   vector<Expr> new_v1;
02188 
02189   for(int j = 0; j < v1Size; ++j)
02190     if(!v3[j]) v2.push_back(v1[j]);
02191     else new_v1.push_back(v1[j]);
02192   v1 = new_v1;
02193 }
02194 
02195 
02196 void TheoryArithOld::VarOrderGraph::selectLargest(const vector<Expr>& v1,
02197                                                vector<Expr>& v2)
02198 {
02199   int v1Size = v1.size();
02200   vector<bool> v3(v1Size);
02201   for(int j=0; j < v1Size; ++j)
02202     v3[j] = false;
02203 
02204   for(int j=0; j < v1Size; ++j) {
02205     if(v3[j]) continue;
02206     for(int i =0; i < v1Size; ++i) {
02207       if((i == j) || v3[i])
02208         continue;
02209       if(lessThan(v1[j],v1[i])) {
02210         v3[j] = true;
02211         break;
02212       }
02213     }
02214   }
02215 
02216   for(int j = 0; j < v1Size; ++j)
02217     if(!v3[j]) v2.push_back(v1[j]);
02218 }
02219 
02220 ///////////////////////////////////////////////////////////////////////////////
02221 // TheoryArithOld Public Methods                                                //
02222 ///////////////////////////////////////////////////////////////////////////////
02223 
02224 
02225 TheoryArithOld::TheoryArithOld(TheoryCore* core)
02226   : TheoryArith(core, "ArithmeticOld"),
02227     d_diseq(core->getCM()->getCurrentContext()),
02228     d_diseqIdx(core->getCM()->getCurrentContext(), 0, 0),
02229     diseqSplitAlready(core->getCM()->getCurrentContext()),
02230     d_inModelCreation(core->getCM()->getCurrentContext(), false, 0),
02231     d_freeConstDB(core->getCM()->getCurrentContext()),
02232     d_buffer_0(core->getCM()->getCurrentContext()),
02233     d_buffer_1(core->getCM()->getCurrentContext()),
02234     d_buffer_2(core->getCM()->getCurrentContext()),
02235     d_buffer_3(core->getCM()->getCurrentContext()),
02236         // Initialize index to 0 at scope 0
02237     d_bufferIdx_0(core->getCM()->getCurrentContext(), 0, 0),
02238     d_bufferIdx_1(core->getCM()->getCurrentContext(), 0, 0),
02239     d_bufferIdx_2(core->getCM()->getCurrentContext(), 0, 0),
02240     d_bufferIdx_3(core->getCM()->getCurrentContext(), 0, 0),
02241     diff_logic_size(core->getCM()->getCurrentContext(), 0, 0),
02242     d_bufferThres(&(core->getFlags()["ineq-delay"].getInt())),
02243     d_splitSign(&(core->getFlags()["nonlinear-sign-split"].getBool())),
02244     d_grayShadowThres(&(core->getFlags()["grayshadow-threshold"].getInt())),
02245     d_countRight(core->getCM()->getCurrentContext()),
02246     d_countLeft(core->getCM()->getCurrentContext()),
02247     d_sharedTerms(core->getCM()->getCurrentContext()),
02248     d_sharedTermsList(core->getCM()->getCurrentContext()),
02249     d_sharedVars(core->getCM()->getCurrentContext()),
02250     bufferedInequalities(core->getCM()->getCurrentContext()),
02251     termLowerBound(core->getCM()->getCurrentContext()),
02252     termLowerBoundThm(core->getCM()->getCurrentContext()),
02253     termUpperBound(core->getCM()->getCurrentContext()),
02254     termUpperBoundThm(core->getCM()->getCurrentContext()),
02255     alreadyProjected(core->getCM()->getCurrentContext()),
02256     dontBuffer(core->getCM()->getCurrentContext()),
02257     diffLogicOnly(core->getCM()->getCurrentContext(), true, 0),
02258     diffLogicGraph(0, core, 0, core->getCM()->getCurrentContext()),
02259     shared_index_1(core->getCM()->getCurrentContext(), 0, 0),
02260     shared_index_2(core->getCM()->getCurrentContext(), 0, 0),
02261     termUpperBounded(core->getCM()->getCurrentContext()),
02262     termLowerBounded(core->getCM()->getCurrentContext()),
02263     termConstrainedBelow(core->getCM()->getCurrentContext()),
02264     termConstrainedAbove(core->getCM()->getCurrentContext())
02265 {
02266   IF_DEBUG(d_diseq.setName("CDList[TheoryArithOld::d_diseq]");)
02267   IF_DEBUG(d_buffer_0.setName("CDList[TheoryArithOld::d_buffer_0]");)
02268   IF_DEBUG(d_buffer_1.setName("CDList[TheoryArithOld::d_buffer_1]");)
02269   IF_DEBUG(d_buffer_2.setName("CDList[TheoryArithOld::d_buffer_2]");)
02270   IF_DEBUG(d_buffer_3.setName("CDList[TheoryArithOld::d_buffer_3]");)
02271   IF_DEBUG(d_bufferIdx_1.setName("CDList[TheoryArithOld::d_bufferIdx_0]");)
02272   IF_DEBUG(d_bufferIdx_1.setName("CDList[TheoryArithOld::d_bufferIdx_1]");)
02273   IF_DEBUG(d_bufferIdx_2.setName("CDList[TheoryArithOld::d_bufferIdx_2]");)
02274   IF_DEBUG(d_bufferIdx_3.setName("CDList[TheoryArithOld::d_bufferIdx_3]");)
02275 
02276   getEM()->newKind(REAL, "_REAL", true);
02277   getEM()->newKind(INT, "_INT", true);
02278   getEM()->newKind(SUBRANGE, "_SUBRANGE", true);
02279 
02280   getEM()->newKind(UMINUS, "_UMINUS");
02281   getEM()->newKind(PLUS, "_PLUS");
02282   getEM()->newKind(MINUS, "_MINUS");
02283   getEM()->newKind(MULT, "_MULT");
02284   getEM()->newKind(DIVIDE, "_DIVIDE");
02285   getEM()->newKind(POW, "_POW");
02286   getEM()->newKind(INTDIV, "_INTDIV");
02287   getEM()->newKind(MOD, "_MOD");
02288   getEM()->newKind(LT, "_LT");
02289   getEM()->newKind(LE, "_LE");
02290   getEM()->newKind(GT, "_GT");
02291   getEM()->newKind(GE, "_GE");
02292   getEM()->newKind(IS_INTEGER, "_IS_INTEGER");
02293   getEM()->newKind(NEGINF, "_NEGINF");
02294   getEM()->newKind(POSINF, "_POSINF");
02295   getEM()->newKind(DARK_SHADOW, "_DARK_SHADOW");
02296   getEM()->newKind(GRAY_SHADOW, "_GRAY_SHADOW");
02297 
02298   getEM()->newKind(REAL_CONST, "_REAL_CONST");
02299 
02300   d_kinds.push_back(REAL);
02301   d_kinds.push_back(INT);
02302   d_kinds.push_back(SUBRANGE);
02303   d_kinds.push_back(IS_INTEGER);
02304   d_kinds.push_back(UMINUS);
02305   d_kinds.push_back(PLUS);
02306   d_kinds.push_back(MINUS);
02307   d_kinds.push_back(MULT);
02308   d_kinds.push_back(DIVIDE);
02309   d_kinds.push_back(POW);
02310   d_kinds.push_back(INTDIV);
02311   d_kinds.push_back(MOD);
02312   d_kinds.push_back(LT);
02313   d_kinds.push_back(LE);
02314   d_kinds.push_back(GT);
02315   d_kinds.push_back(GE);
02316   d_kinds.push_back(RATIONAL_EXPR);
02317   d_kinds.push_back(NEGINF);
02318   d_kinds.push_back(POSINF);
02319   d_kinds.push_back(DARK_SHADOW);
02320   d_kinds.push_back(GRAY_SHADOW);
02321   d_kinds.push_back(REAL_CONST);
02322 
02323   registerTheory(this, d_kinds, true);
02324 
02325   d_rules = createProofRulesOld();
02326   diffLogicGraph.setRules(d_rules);
02327   diffLogicGraph.setArith(this);
02328 
02329   d_realType = Type(getEM()->newLeafExpr(REAL));
02330   d_intType  = Type(getEM()->newLeafExpr(INT));
02331 
02332   // Make the zero variable
02333   Theorem thm_exists_zero = getCommonRules()->varIntroSkolem(rat(0));
02334   zero = thm_exists_zero.getExpr()[1];
02335 }
02336 
02337 
02338 // Destructor: delete the proof rules class if it's present
02339 TheoryArithOld::~TheoryArithOld() {
02340   if(d_rules != NULL) delete d_rules;
02341   // Clear the inequality databases
02342   for(ExprMap<CDList<Ineq> *>::iterator i=d_inequalitiesRightDB.begin(),
02343   iend=d_inequalitiesRightDB.end(); i!=iend; ++i) {
02344     delete (i->second);
02345     free(i->second);
02346   }
02347   for(ExprMap<CDList<Ineq> *>::iterator i=d_inequalitiesLeftDB.begin(),
02348   iend=d_inequalitiesLeftDB.end(); i!=iend; ++i) {
02349     delete (i->second);
02350     free (i->second);
02351   }
02352   unregisterTheory(this, d_kinds, true);
02353 }
02354 
02355 void TheoryArithOld::collectVars(const Expr& e, vector<Expr>& vars,
02356             set<Expr>& cache) {
02357   // Check the cache first
02358   if(cache.count(e) > 0) return;
02359   // Not processed yet.  Cache the expression and proceed
02360   cache.insert(e);
02361   if(isLeaf(e)) vars.push_back(e);
02362   else
02363     for(Expr::iterator i=e.begin(), iend=e.end(); i!=iend; ++i)
02364       collectVars(*i, vars, cache);
02365 }
02366 
02367 void
02368 TheoryArithOld::processFiniteInterval
02369 (const Theorem& alphaLEax,
02370            const Theorem& bxLEbeta) {
02371   const Expr& ineq1(alphaLEax.getExpr());
02372   const Expr& ineq2(bxLEbeta.getExpr());
02373   DebugAssert(isLE(ineq1), "TheoryArithOld::processFiniteInterval: ineq1 = "
02374         +ineq1.toString());
02375   DebugAssert(isLE(ineq2), "TheoryArithOld::processFiniteInterval: ineq2 = "
02376         +ineq2.toString());
02377   // If the inequalities are not integer, just return (nothing to do)
02378   if(!isInteger(ineq1[0])
02379      || !isInteger(ineq1[1])
02380      || !isInteger(ineq2[0])
02381      || !isInteger(ineq2[1]))
02382     return;
02383 
02384   const Expr& ax = ineq1[1];
02385   const Expr& bx = ineq2[0];
02386   DebugAssert(!isPlus(ax) && !isRational(ax),
02387         "TheoryArithOld::processFiniteInterval:\n ax = "+ax.toString());
02388   DebugAssert(!isPlus(bx) && !isRational(bx),
02389         "TheoryArithOld::processFiniteInterval:\n bx = "+bx.toString());
02390   Expr a = isMult(ax)? ax[0] : rat(1);
02391   Expr b = isMult(bx)? bx[0] : rat(1);
02392 
02393   Theorem thm1(alphaLEax), thm2(bxLEbeta);
02394   // Multiply the inequalities by 'b' and 'a', and canonize them, if necessary
02395   if(a != b) {
02396     thm1 = canonPred(iffMP(alphaLEax, d_rules->multIneqn(ineq1, b)));
02397     thm2 = canonPred(iffMP(bxLEbeta, d_rules->multIneqn(ineq2, a)));
02398   }
02399   // Check that a*beta - b*alpha == c > 0
02400   const Expr& alphaLEt = thm1.getExpr();
02401   const Expr& alpha = alphaLEt[0];
02402   const Expr& t = alphaLEt[1];
02403   const Expr& beta = thm2.getExpr()[1];
02404   Expr c = canon(beta - alpha).getRHS();
02405 
02406   if(c.isRational() && c.getRational() >= 1) {
02407     // This is a finite interval.  First, derive t <= alpha + c:
02408     // canon(alpha+c) => (alpha+c == beta) ==> [symmetry] beta == alpha+c
02409     // Then substitute that in thm2
02410     Theorem bEQac = symmetryRule(canon(alpha + c));
02411     // Substitute beta == alpha+c for the second child of thm2
02412     vector<unsigned> changed;
02413     vector<Theorem> thms;
02414     changed.push_back(1);
02415     thms.push_back(bEQac);
02416     Theorem tLEac = substitutivityRule(thm2.getExpr(), changed, thms);
02417     tLEac = iffMP(thm2, tLEac);
02418     // Derive and enqueue the finite interval constraint
02419     Theorem isInta(isIntegerThm(alpha));
02420     Theorem isIntt(isIntegerThm(t));
02421     if (d_sharedTerms.find(thm1.getExpr()[1]) != d_sharedTerms.end())
02422       enqueueFact(d_rules->finiteInterval(thm1, tLEac, isInta, isIntt));
02423   }
02424 }
02425 
02426 
02427 void
02428 TheoryArithOld::processFiniteIntervals(const Expr& x) {
02429   // If x is not integer, do not bother
02430   if(!isInteger(x)) return;
02431   // Process every pair of the opposing inequalities for 'x'
02432   ExprMap<CDList<Ineq> *>::iterator iLeft, iRight;
02433   iLeft = d_inequalitiesLeftDB.find(x);
02434   if(iLeft == d_inequalitiesLeftDB.end()) return;
02435   iRight = d_inequalitiesRightDB.find(x);
02436   if(iRight == d_inequalitiesRightDB.end()) return;
02437   // There are some opposing inequalities; get the lists
02438   CDList<Ineq>& ineqsLeft = *(iLeft->second);
02439   CDList<Ineq>& ineqsRight = *(iRight->second);
02440   // Get the sizes of the lists
02441   size_t sizeLeft = ineqsLeft.size();
02442   size_t sizeRight = ineqsRight.size();
02443   // Process all the pairs of the opposing inequalities
02444   for(size_t l=0; l<sizeLeft; ++l)
02445     for(size_t r=0; r<sizeRight; ++r)
02446       processFiniteInterval(ineqsRight[r], ineqsLeft[l]);
02447 }
02448 
02449 /*! This function recursively decends expression tree <strong>without
02450  *  caching</strong> until it hits a node that is already setup.  Be
02451  *  careful on what expressions you are calling it.
02452  */
02453 void
02454 TheoryArithOld::setupRec(const Expr& e) {
02455   if(e.hasFind()) return;
02456   // First, set up the kids recursively
02457   for (int k = 0; k < e.arity(); ++k) {
02458     setupRec(e[k]);
02459   }
02460   // Create a find pointer for e
02461   e.setFind(reflexivityRule(e));
02462   e.setEqNext(reflexivityRule(e));
02463   // And call our own setup()
02464   setup(e);
02465 }
02466 
02467 
02468 void TheoryArithOld::addSharedTerm(const Expr& e) {
02469   return;
02470   if (d_sharedTerms.find(e) == d_sharedTerms.end()) {
02471     d_sharedTerms[e] = true;
02472     d_sharedTermsList.push_back(e);
02473   }
02474 }
02475 
02476 
02477 void TheoryArithOld::assertFact(const Theorem& e)
02478 {
02479   TRACE("arith assert", "assertFact(", e.getExpr().toString(), ")");
02480 
02481     // Pick up any multiplicative case splits and enqueue them
02482     for (unsigned i = 0; i < multiplicativeSignSplits.size(); i ++)
02483       enqueueFact(multiplicativeSignSplits[i]);
02484     multiplicativeSignSplits.clear();
02485 
02486   const Expr& expr = e.getExpr();
02487   if (expr.isNot() && expr[0].isEq()) {
02488     IF_DEBUG(debugger.counter("[arith] received disequalities")++;)
02489 
02490 //    Expr eq = expr[0];
02491 //
02492 //    // We want to expand on difference logic disequalities as soon as possible
02493 //    bool diff_logic = false;
02494 //    if (eq[1].isRational() && eq[1].getRational() == 0) {
02495 //      if (!isPlus(eq[0])) {
02496 //        if (isLeaf(eq[0])) diff_logic = true;
02497 //      }
02498 //      else {
02499 //        int arity = eq[0].arity();
02500 //        if (arity <= 2) {
02501 //          if (eq[0][0].isRational())
02502 //            diff_logic = true;
02503 //          else {
02504 //            Expr ax = eq[0][0], a, x;
02505 //            Expr by = eq[0][1], b, y;
02506 //            separateMonomial(ax, a, x);
02507 //            separateMonomial(by, b, y);
02508 //            if (isLeaf(x) && isLeaf(y))
02509 //              if ((a.getRational() == 1 && b.getRational() == -1) ||
02510 //                (a.getRational() == -1 && b.getRational() == 1))
02511 //                diff_logic = true;
02512 //          }
02513 //        }
02514 //        if (arity == 3 && eq[0][0].isRational()) {
02515 //          Expr ax = eq[0][1], a, x;
02516 //        Expr by = eq[0][2], b, y;
02517 //        separateMonomial(ax, a, x);
02518 //        separateMonomial(by, b, y);
02519 //        if (isLeaf(x) && isLeaf(y))
02520 //          if ((a.getRational() == 1 && b.getRational() == -1) ||
02521 //            (a.getRational() == -1 && b.getRational() == 1))
02522 //            diff_logic = true;
02523 //        }
02524 //      }
02525 //    }
02526 //
02527 //    if (diff_logic)
02528 //      enqueueFact(d_rules->diseqToIneq(e));
02529 //    else
02530       d_diseq.push_back(e);
02531   }
02532   else if (!expr.isEq()){
02533     if (expr.isNot()) {
02534       // If expr[0] is asserted to *not* be an integer, we track it
02535       // so we will detect if it ever becomes equal to an integer.
02536       if (expr[0].getKind() == IS_INTEGER) {
02537         expr[0][0].addToNotify(this, expr[0]);
02538       }
02539       // This can only be negation of dark or gray shadows, or
02540       // disequalities, which we ignore.  Negations of inequalities
02541       // are handled in rewrite, we don't even receive them here.
02542 
02543 //      if (isGrayShadow(expr[0])) {
02544 //        TRACE("arith gray", "expanding ", expr.toString(), "");
02545 //        Theorem expand = d_rules->expandGrayShadowRewrite(expr[0]);
02546 //        enqueueFact(iffMP(e, substitutivityRule(expr, 0, expand)));
02547 //      }
02548 
02549     }
02550     else if(isDarkShadow(expr)) {
02551       enqueueFact(d_rules->expandDarkShadow(e));
02552       IF_DEBUG(debugger.counter("received DARK_SHADOW")++;)
02553     }
02554     else if(isGrayShadow(expr)) {
02555       IF_DEBUG(debugger.counter("received GRAY_SHADOW")++;)
02556       const Rational& c1 = expr[2].getRational();
02557       const Rational& c2 = expr[3].getRational();
02558 
02559       // If gray shadow bigger than the treshold, we are done
02560       if (*d_grayShadowThres > -1 && (c2 - c1 > *d_grayShadowThres)) {
02561         setIncomplete("Some gray shadows ignored due to threshold");
02562         return;
02563       }
02564 
02565       const Expr& v = expr[0];
02566       const Expr& ee = expr[1];
02567       if(c1 == c2)
02568         enqueueFact(d_rules->expandGrayShadow0(e));
02569       else {
02570         Theorem gThm(e);
02571         // Check if we can reduce the number of cases in G(ax,c,c1,c2)
02572         if(ee.isRational() && isMult(v)
02573             && v[0].isRational() && v[0].getRational() >= 2) {
02574           IF_DEBUG(debugger.counter("reduced const GRAY_SHADOW")++;)
02575           gThm = d_rules->grayShadowConst(e);
02576         }
02577         // (Possibly) new gray shadow
02578         const Expr& g = gThm.getExpr();
02579         if(g.isFalse())
02580           setInconsistent(gThm);
02581         else if(g[2].getRational() == g[3].getRational())
02582           enqueueFact(d_rules->expandGrayShadow0(gThm));
02583         else if(g[3].getRational() - g[2].getRational() <= 5) {
02584           // Assert c1+e <= v <= c2+e
02585           enqueueFact(d_rules->expandGrayShadow(gThm));
02586           // Split G into 2 cases x = l_bound and the other
02587           Theorem thm2 = d_rules->splitGrayShadowSmall(gThm);
02588           enqueueFact(thm2);
02589         }
02590         else {
02591           // Assert c1+e <= v <= c2+e
02592           enqueueFact(d_rules->expandGrayShadow(gThm));
02593           // Split G into 2 cases (binary search b/w c1 and c2)
02594           Theorem thm2 = d_rules->splitGrayShadow(gThm);
02595           enqueueFact(thm2);
02596           // Fetch the two gray shadows
02597 //          DebugAssert(thm2.getExpr().isAnd() && thm2.getExpr().arity()==2,
02598 //              "thm2 = "+thm2.getExpr().toString());
02599 //          const Expr& G1orG2 = thm2.getExpr()[0];
02600 //          DebugAssert(G1orG2.isOr() && G1orG2.arity()==2,
02601 //              "G1orG2 = "+G1orG2.toString());
02602 //          const Expr& G1 = G1orG2[0];
02603 //          const Expr& G2 = G1orG2[1];
02604 //          DebugAssert(G1.getKind()==GRAY_SHADOW, "G1 = "+G1.toString());
02605 //          DebugAssert(G2.getKind()==GRAY_SHADOW, "G2 = "+G2.toString());
02606 //          // Split on the left disjunct first (keep the priority low)
02607 //          Expr tmp = simplifyExpr(G1);
02608 //          if (!tmp.isBoolConst())
02609 //            addSplitter(tmp, 1);
02610 //          tmp = simplifyExpr(G2);
02611 //          if (!tmp.isBoolConst())
02612 //            addSplitter(tmp, -1);
02613         }
02614       }
02615     }
02616     else {
02617       DebugAssert(isLE(expr) || isLT(expr) || isIntPred(expr),
02618       "expected LE or LT: "+expr.toString());
02619       if(isLE(expr) || isLT(expr)) {
02620   IF_DEBUG(debugger.counter("recevied inequalities")++;)
02621 
02622 //        // Assert the equivalent negated inequality
02623 //        Theorem thm;
02624 //        if (isLE(expr)) thm = d_rules->negatedInequality(!gtExpr(expr[0],expr[1]));
02625 //        else thm = d_rules->negatedInequality(!geExpr(expr[0],expr[1]));
02626 //        thm = symmetryRule(thm);
02627 //        Theorem thm2 = simplify(thm.getRHS()[0]);
02628 //        DebugAssert(thm2.getLHS() != thm2.getRHS(), "Expected rewrite");
02629 //        thm2 = getCommonRules()->substitutivityRule(thm.getRHS(), thm2);
02630 //        thm = transitivityRule(thm, thm2);
02631 //        enqueueFact(iffMP(e, thm));
02632 
02633   // Buffer the inequality
02634   addToBuffer(e);
02635 
02636   unsigned total_buf_size = d_buffer_0.size() + d_buffer_1.size() + d_buffer_2.size() + d_buffer_3.size();
02637   unsigned processed      = d_bufferIdx_0 + d_bufferIdx_1 + d_bufferIdx_2 + d_bufferIdx_3;
02638   TRACE("arith ineq", "buffer.size() = ", total_buf_size,
02639           ", index="+int2string(processed)
02640           +", threshold="+int2string(*d_bufferThres));
02641 
02642   if(!diffLogicOnly && *d_bufferThres >= 0 && (total_buf_size > *d_bufferThres + processed) && !d_inModelCreation) {
02643     processBuffer();
02644   }
02645       } else {
02646   IF_DEBUG(debugger.counter("arith IS_INTEGER")++;)
02647         if (!isInteger(expr[0])) {
02648           enqueueFact(d_rules->IsIntegerElim(e));
02649         }
02650       }
02651     }
02652   }
02653   else {
02654     IF_DEBUG(debugger.counter("[arith] received   t1=t2")++;)
02655 
02656 //    const Expr lhs = e.getExpr()[0];
02657 //    const Expr rhs = e.getExpr()[1];
02658 //
02659 //    CDMap<Expr, Rational>::iterator l_bound_find = termLowerBound[lhs];
02660 //    if (l_bound_find != termLowerBound.end()) {
02661 //      Rational lhs_bound = (*l_bound_find).second;
02662 //      CDMap<Expr, Rational>::iterator l_bound_find_rhs = termLowerBound[rhs];
02663 //      if (l_bound_find_rhs != termLowerBound.end()) {
02664 //
02665 //      } else {
02666 //        // Add the new bound for the rhs
02667 //        termLowerBound[rhs] = lhs_bound;
02668 //        termLowerBoundThm =
02669 //      }
02670 //
02671 //    }
02672 
02673 
02674   }
02675 }
02676 
02677 
02678 void TheoryArithOld::checkSat(bool fullEffort)
02679 {
02680   //  vector<Expr>::const_iterator e;
02681   //  vector<Expr>::const_iterator eEnd;
02682   // TODO: convert back to use iterators
02683   TRACE("arith checksat", "checksat(fullEffort = ", fullEffort? "true, modelCreation = " : "false, modelCreation = ", (d_inModelCreation ? "true)" : "false)"));
02684   TRACE("arith ineq", "TheoryArithOld::checkSat(fullEffort=",
02685         fullEffort? "true" : "false", ")");
02686   if (fullEffort) {
02687 
02688     // Process the buffer if necessary
02689     if (!inconsistent())
02690         processBuffer();
02691 
02692     // Expand the needded inequalitites
02693     int total_buffer_size = d_buffer_0.size() + d_buffer_1.size() + d_buffer_2.size() + d_buffer_3.size();
02694 
02695     int constrained_vars = 0;
02696     if (!inconsistent() && total_buffer_size > 0)
02697       constrained_vars = computeTermBounds();
02698 
02699     bool something_enqueued = false;
02700 
02701     if (d_inModelCreation || (!inconsistent() && total_buffer_size > 0 && constrained_vars > 0)) {
02702       // If in model creation we might have to reconsider some of the dis-equalities
02703       if (d_inModelCreation) d_diseqIdx = 0;
02704 
02705       // Now go and try to split
02706       for(; d_diseqIdx < d_diseq.size(); d_diseqIdx = d_diseqIdx+1) {
02707         TRACE("model", "[arith] refining diseq: ", d_diseq[d_diseqIdx].getExpr() , "");
02708 
02709         // Get the disequality theorem and the expression
02710         Theorem diseqThm = d_diseq[d_diseqIdx];
02711         Expr diseq = diseqThm.getExpr();
02712 
02713         // If we split on this one already
02714         if (diseqSplitAlready.find(diseq) != diseqSplitAlready.end()) continue;
02715 
02716         // Get the equality
02717         Expr eq = diseq[0];
02718 
02719         // Get the left-hand-side and the right-hands side
02720         Expr lhs = eq[0];
02721         Expr rhs = eq[1];
02722         DebugAssert(lhs.hasFind() && rhs.hasFind(), "Part of dis-equality has no find!");
02723         lhs = find(lhs).getRHS();
02724         rhs = find(rhs).getRHS();
02725 
02726         // If the value of the equality is already determined by instantiation, we just skip it
02727         // This can happen a lot as we infer equalities in difference logic
02728         if (lhs.isRational() && rhs.isRational()) {
02729           TRACE("arith diseq", "disequality already evaluated : ", diseq.toString(), "");
02730           continue;
02731         }
02732 
02733         // We can allow ourselfs not to care about specific values if we are
02734         // not in model creation
02735         if (!d_inModelCreation) {
02736           // If the left or the right hand side is unbounded, we don't care right now
02737           if (!isConstrained(lhs) || !isConstrained(rhs)) continue;
02738           if (getUpperBound(lhs) < getLowerBound(rhs)) continue;
02739           if (getUpperBound(rhs) < getLowerBound(lhs)) continue;
02740         }
02741 
02742         TRACE("arith ineq", "[arith] refining diseq: ", d_diseq[d_diseqIdx].getExpr() , "");
02743 
02744         // We don't know the value of the disequlaity, split on it (for now)
02745         enqueueFact(d_rules->diseqToIneq(diseqThm));
02746         something_enqueued = true;
02747 
02748         // Mark it as split already
02749         diseqSplitAlready[diseq] = true;
02750       }
02751     }
02752 
02753     IF_DEBUG(
02754             {
02755               bool dejans_printouts = false;
02756               if (dejans_printouts) {
02757         cerr << "Disequalities after CheckSat" << endl;
02758         for (unsigned i = 0; i < d_diseq.size(); i ++) {
02759           Expr diseq = d_diseq[i].getExpr();
02760           Expr d_find = find(diseq[0]).getRHS();
02761           cerr << diseq.toString() << ":" << d_find.toString() << endl;
02762         }
02763         cerr << "Arith Buffer after CheckSat (0)" << endl;
02764         for (unsigned i = 0; i < d_buffer_0.size(); i ++) {
02765           Expr ineq = d_buffer_0[i].getExpr();
02766           Expr rhs = find(ineq[1]).getRHS();
02767           cerr << ineq.toString() << ":" << rhs.toString() << endl;
02768         }
02769         cerr << "Arith Buffer after CheckSat (1)" << endl;
02770         for (unsigned i = 0; i < d_buffer_1.size(); i ++) {
02771           Expr ineq = d_buffer_1[i].getExpr();
02772           Expr rhs = find(ineq[1]).getRHS();
02773           cerr << ineq.toString() << ":" << rhs.toString() << endl;
02774         }
02775         cerr << "Arith Buffer after CheckSat (2)" << endl;
02776         for (unsigned i = 0; i < d_buffer_2.size(); i ++) {
02777           Expr ineq = d_buffer_2[i].getExpr();
02778           Expr rhs = find(ineq[1]).getRHS();
02779           cerr << ineq.toString() << ":" << rhs.toString() << endl;
02780         }
02781         cerr << "Arith Buffer after CheckSat (3)" << endl;
02782         for (unsigned i = 0; i < d_buffer_3.size(); i ++) {
02783           Expr ineq = d_buffer_3[i].getExpr();
02784           Expr rhs = find(ineq[1]).getRHS();
02785           cerr << ineq.toString() << ":" << rhs.toString() << endl;
02786           }
02787               }
02788             }
02789     )
02790   }
02791 }
02792 
02793 
02794 
02795 void TheoryArithOld::refineCounterExample()
02796 {
02797   d_inModelCreation = true;
02798   TRACE("model", "refineCounterExample[TheoryArithOld] ", "", "{");
02799   CDMap<Expr, bool>::iterator it = d_sharedTerms.begin(), it2,
02800     iend = d_sharedTerms.end();
02801   // Add equalities over all pairs of shared terms as suggested
02802   // splitters.  Notice, that we want to split on equality
02803   // (positively) first, to reduce the size of the model.
02804   for(; it!=iend; ++it) {
02805     // Copy by value: the elements in the pair from *it are NOT refs in CDMap
02806     Expr e1 = (*it).first;
02807     for(it2 = it, ++it2; it2!=iend; ++it2) {
02808       Expr e2 = (*it2).first;
02809       DebugAssert(isReal(getBaseType(e1)),
02810       "TheoryArithOld::refineCounterExample: e1 = "+e1.toString()
02811       +"\n type(e1) = "+e1.getType().toString());
02812       if(findExpr(e1) != findExpr(e2)) {
02813   DebugAssert(isReal(getBaseType(e2)),
02814         "TheoryArithOld::refineCounterExample: e2 = "+e2.toString()
02815         +"\n type(e2) = "+e2.getType().toString());
02816   Expr eq = simplifyExpr(e1.eqExpr(e2));
02817         if (!eq.isBoolConst()) {
02818           addSplitter(eq);
02819         }
02820       }
02821     }
02822   }
02823   TRACE("model", "refineCounterExample[Theory::Arith] ", "", "}");
02824 }
02825 
02826 
02827 void
02828 TheoryArithOld::findRationalBound(const Expr& varSide, const Expr& ratSide,
02829              const Expr& var,
02830              Rational &r)
02831 {
02832   Expr c, x;
02833   separateMonomial(varSide, c, x);
02834 
02835   if (!findExpr(ratSide).isRational() && isNonlinearEq(ratSide.eqExpr(rat(0))))
02836       throw ArithException("Could not generate the model due to non-linear arithmetic");
02837 
02838   DebugAssert(findExpr(c).isRational(),
02839         "seperateMonomial failed");
02840   DebugAssert(findExpr(ratSide).isRational(),
02841         "smallest variable in graph, should not have variables"
02842         " in inequalities: ");
02843   DebugAssert(x == var, "separateMonomial found different variable: "
02844         + var.toString());
02845   r = findExpr(ratSide).getRational() / findExpr(c).getRational();
02846 }
02847 
02848 bool
02849 TheoryArithOld::findBounds(const Expr& e, Rational& lub, Rational&  glb)
02850 {
02851   bool strictLB=false, strictUB=false;
02852   bool right = (d_inequalitiesRightDB.count(e) > 0
02853            && d_inequalitiesRightDB[e]->size() > 0);
02854   bool left = (d_inequalitiesLeftDB.count(e) > 0
02855          && d_inequalitiesLeftDB[e]->size() > 0);
02856   int numRight = 0, numLeft = 0;
02857   if(right) { //rationals less than e
02858     CDList<Ineq> * ratsLTe = d_inequalitiesRightDB[e];
02859     for(unsigned int i=0; i<ratsLTe->size(); i++) {
02860       DebugAssert((*ratsLTe)[i].varOnRHS(), "variable on wrong side!");
02861       Expr ineq = (*ratsLTe)[i].ineq().getExpr();
02862       Expr leftSide = ineq[0], rightSide = ineq[1];
02863       Rational r;
02864       findRationalBound(rightSide, leftSide, e , r);
02865       if(numRight==0 || r>glb){
02866   glb = r;
02867   strictLB = isLT(ineq);
02868       }
02869       numRight++;
02870     }
02871     TRACE("model", "   =>Lower bound ", glb.toString(), "");
02872   }
02873   if(left) {   //rationals greater than e
02874     CDList<Ineq> * ratsGTe = d_inequalitiesLeftDB[e];
02875     for(unsigned int i=0; i<ratsGTe->size(); i++) {
02876       DebugAssert((*ratsGTe)[i].varOnLHS(), "variable on wrong side!");
02877       Expr ineq = (*ratsGTe)[i].ineq().getExpr();
02878       Expr leftSide = ineq[0], rightSide = ineq[1];
02879       Rational r;
02880       findRationalBound(leftSide, rightSide, e, r);
02881       if(numLeft==0 || r<lub) {
02882   lub = r;
02883   strictUB = isLT(ineq);
02884       }
02885       numLeft++;
02886     }
02887     TRACE("model", "   =>Upper bound ", lub.toString(), "");
02888   }
02889   if(!left && !right) {
02890     lub = 0;
02891       glb = 0;
02892   }
02893   if(!left && right) {lub = glb +2;}
02894   if(!right && left)  {glb =  lub-2;}
02895   DebugAssert(glb <= lub, "Greatest lower bound needs to be smaller "
02896         "than least upper bound");
02897   return strictLB;
02898 }
02899 
02900 void TheoryArithOld::assignVariables(std::vector<Expr>&v)
02901 {
02902   int count = 0;
02903 
02904   if (diffLogicOnly)
02905   {
02906     // Compute the model
02907     diffLogicGraph.computeModel();
02908     // Get values for the variables
02909     for (unsigned i = 0; i < v.size(); i ++) {
02910       Expr x = v[i];
02911       assignValue(x, rat(diffLogicGraph.getValuation(x)));
02912     }
02913     // Done
02914     return;
02915   }
02916 
02917   while (v.size() > 0)
02918   {
02919     std::vector<Expr> bottom;
02920     d_graph.selectSmallest(v, bottom);
02921     TRACE("model", "Finding variables to assign. Iteration # ", count, "");
02922     for(unsigned int i = 0; i<bottom.size(); i++)
02923     {
02924       Expr e = bottom[i];
02925       TRACE("model", "Found: ", e, "");
02926       // Check if it is already a concrete constant
02927       if(e.isRational()) continue;
02928 
02929       Rational lub, glb;
02930       bool strictLB;
02931       strictLB = findBounds(e, lub, glb);
02932       Rational mid;
02933       if(isInteger(e)) {
02934         if(strictLB && glb.isInteger())
02935           mid = glb + 1;
02936         else
02937           mid = ceil(glb);
02938       }
02939       else
02940         mid = (lub + glb)/2;
02941 
02942       TRACE("model", "Assigning mid = ", mid, " {");
02943       assignValue(e, rat(mid));
02944       TRACE("model", "Assigned find(e) = ", findExpr(e), " }");
02945       if(inconsistent()) return; // Punt immediately if failed
02946     }
02947     count++;
02948   }
02949 }
02950 
02951 void TheoryArithOld::computeModelBasic(const std::vector<Expr>& v)
02952 {
02953   d_inModelCreation = true;
02954   vector<Expr> reps;
02955   TRACE("model", "Arith=>computeModel ", "", "{");
02956   for(unsigned int i=0; i <v.size(); ++i) {
02957     const Expr& e = v[i];
02958     if(findExpr(e) == e) {
02959       TRACE("model", "arith variable:", e , "");
02960       reps.push_back(e);
02961     }
02962     else {
02963       TRACE("model", "arith variable:", e , "");
02964       TRACE("model", " ==> is defined by: ", findExpr(e) , "");
02965     }
02966   }
02967   assignVariables(reps);
02968   TRACE("model", "Arith=>computeModel", "", "}");
02969   d_inModelCreation = false;
02970 }
02971 
02972 // For any arith expression 'e', if the subexpressions are assigned
02973 // concrete values, then find(e) must already be a concrete value.
02974 void TheoryArithOld::computeModel(const Expr& e, vector<Expr>& vars) {
02975   DebugAssert(findExpr(e).isRational(), "TheoryArithOld::computeModel("
02976         +e.toString()+")\n e is not assigned concrete value.\n"
02977         +" find(e) = "+findExpr(e).toString());
02978   assignValue(simplify(e));
02979   vars.push_back(e);
02980 }
02981 
02982 Theorem TheoryArithOld::checkIntegerEquality(const Theorem& thm) {
02983 
02984   // Check if this is a rewrite theorem
02985   bool rewrite = thm.isRewrite();
02986 
02987   // If it's an integer theorem, then rafine it to integer domain
02988   Expr eq = (rewrite ? thm.getRHS() : thm.getExpr());
02989 
02990   TRACE("arith rafine", "TheoryArithOld::checkIntegerEquality(", eq, ")");
02991   DebugAssert(eq.getKind() == EQ, "checkIntegerEquality: must be an equality");
02992 
02993   // Trivial equalities, we don't care
02994   if (!isPlus(eq[1]) && !isPlus(eq[0])) return thm;
02995   Expr old_sum = (isPlus(eq[1]) ? eq[1] : eq[0]);
02996 
02997   // Get the sum part
02998   vector<Expr> children;
02999   bool const_is_integer = true; // Assuming only one constant is present (canon called before this)
03000   for (int i = 0; i < old_sum.arity(); i ++)
03001      if (!old_sum[i].isRational())
03002        children.push_back(old_sum[i]);
03003      else
03004        const_is_integer = old_sum[i].getRational().isInteger();
03005 
03006   // If the constants are integers, we don't care
03007   if (const_is_integer) return thm;
03008 
03009   Expr sum = (children.size() > 1 ? plusExpr(children) : children[0]);
03010   // Check for integer of the remainder of the sum
03011   Theorem isIntegerEquality = isIntegerThm(sum);
03012   // If it is an integer, it's unsat
03013   if (!isIntegerEquality.isNull()) {
03014       Theorem false_thm = d_rules->intEqualityRationalConstant(isIntegerEquality, eq);
03015         if (rewrite) return transitivityRule(thm, false_thm);
03016         else return iffMP(thm, false_thm);
03017   }
03018   else return thm;
03019 }
03020 
03021 
03022 Theorem TheoryArithOld::rafineInequalityToInteger(const Theorem& thm) {
03023 
03024   // Check if this is a rewrite theorem
03025   bool rewrite = thm.isRewrite();
03026 
03027   // If it's an integer theorem, then rafine it to integer domain
03028   Expr ineq = (rewrite ? thm.getRHS() : thm.getExpr());
03029 
03030   TRACE("arith rafine", "TheoryArithOld::rafineInequalityToInteger(", ineq, ")");
03031   DebugAssert(isIneq(ineq), "rafineInequalityToInteger: must be an inequality");
03032 
03033   // Trivial inequalities are rafined
03034   // if (!isPlus(ineq[1])) return thm;
03035 
03036   // Get the sum part
03037   vector<Expr> children;
03038   if (isPlus(ineq[1])) {
03039     for (int i = 0; i < ineq[1].arity(); i ++)
03040       if (!ineq[1][i].isRational())
03041         children.push_back(ineq[1][i]);
03042   } else children.push_back(ineq[1]);
03043 
03044   Expr sum = (children.size() > 1 ? plusExpr(children) : children[0]);
03045   // Check for integer of the remainder of the sum
03046   Theorem isIntegerInequality = isIntegerThm(sum);
03047   // If it is an integer, do rafine it
03048   if (!isIntegerInequality.isNull()) {
03049         Theorem rafine = d_rules->rafineStrictInteger(isIntegerInequality, ineq);
03050         TRACE("arith rafine", "TheoryArithOld::rafineInequalityToInteger()", "=>", rafine.getRHS());
03051         if (rewrite) return canonPredEquiv(transitivityRule(thm, rafine));
03052         else return canonPred(iffMP(thm, rafine));
03053   }
03054   else return thm;
03055 }
03056 
03057 
03058 
03059 /*! accepts a rewrite theorem over eqn|ineqn and normalizes it
03060  *  and returns a theorem to that effect. assumes e is non-trivial
03061  *  i.e. e is not '0=const' or 'const=0' or '0 <= const' etc.
03062  */
03063 Theorem TheoryArithOld::normalize(const Expr& e) {
03064   //e is an eqn or ineqn. e is not a trivial eqn or ineqn
03065   //trivial means 0 = const or 0 <= const.
03066   TRACE("arith normalize", "normalize(", e, ") {");
03067   DebugAssert(e.isEq() || isIneq(e),
03068         "normalize: input must be Eq or Ineq: " + e.toString());
03069   DebugAssert(!isIneq(e) || (0 == e[0].getRational()),
03070         "normalize: if (e is ineq) then e[0] must be 0" +
03071         e.toString());
03072   if(e.isEq()) {
03073     if(e[0].isRational()) {
03074       DebugAssert(0 == e[0].getRational(),
03075       "normalize: if e is Eq and e[0] is rat then e[0]==0");
03076     }
03077     else {
03078       //if e[0] is not rational then e[1] must be rational.
03079       DebugAssert(e[1].isRational() && 0 == e[1].getRational(),
03080       "normalize: if e is Eq and e[1] is rat then e[1]==0\n"
03081       " e = "+e.toString());
03082     }
03083   }
03084 
03085   Expr factor;
03086   if(e[0].isRational())
03087     factor = computeNormalFactor(e[1], false);
03088   else
03089     factor = computeNormalFactor(e[0], false);
03090 
03091   TRACE("arith normalize", "normalize: factor = ", factor, "");
03092   DebugAssert(factor.getRational() > 0,
03093               "normalize: factor="+ factor.toString());
03094 
03095   Theorem thm(reflexivityRule(e));
03096   // Now multiply the equality by the factor, unless it is 1
03097   if(factor.getRational() != 1) {
03098     int kind = e.getKind();
03099     switch(kind) {
03100     case EQ:
03101       //TODO: DEJAN FIX
03102       thm = d_rules->multEqn(e[0], e[1], factor);
03103       // And canonize the result
03104       thm = canonPredEquiv(thm);
03105 
03106       // If this is an equation of the form 0 = c + sum, c is not integer, but sum is
03107       // then equation has no solutions
03108       thm = checkIntegerEquality(thm);
03109 
03110       break;
03111     case LE:
03112     case LT:
03113     case GE:
03114     case GT: {
03115        thm = d_rules->multIneqn(e, factor);
03116        // And canonize the result
03117        thm = canonPredEquiv(thm);
03118        // Try to rafine to integer domain
03119        thm = rafineInequalityToInteger(thm);
03120        break;
03121     }
03122 
03123     default:
03124       // MS .net doesn't accept "..." + int
03125       ostringstream ss;
03126       ss << "normalize: control should not reach here " << kind;
03127       DebugAssert(false, ss.str());
03128       break;
03129     }
03130   } else
03131     if (e.getKind() == EQ)
03132       thm = checkIntegerEquality(thm);
03133 
03134   TRACE("arith normalize", "normalize => ", thm, " }");
03135   return(thm);
03136 }
03137 
03138 
03139 Theorem TheoryArithOld::normalize(const Theorem& eIffEqn) {
03140   if (eIffEqn.isRewrite()) return transitivityRule(eIffEqn, normalize(eIffEqn.getRHS()));
03141   else return iffMP(eIffEqn, normalize(eIffEqn.getExpr()));
03142 }
03143 
03144 
03145 Theorem TheoryArithOld::rewrite(const Expr& e)
03146 {
03147   DebugAssert(leavesAreSimp(e), "Expected leaves to be simplified");
03148   TRACE("arith", "TheoryArithOld::rewrite(", e, ") {");
03149   Theorem thm;
03150   if (!e.isTerm()) {
03151     if (!e.isAbsLiteral()) {
03152       if (e.isPropAtom() && leavesAreNumConst(e)) {
03153         if (e.getSize() < 200) {
03154           Expr eNew = e;
03155           thm = reflexivityRule(eNew);
03156           while (eNew.containsTermITE()) {
03157             thm = transitivityRule(thm, getCommonRules()->liftOneITE(eNew));
03158             DebugAssert(!thm.isRefl(), "Expected non-reflexive");
03159             thm = transitivityRule(thm, theoryCore()->getCoreRules()->rewriteIteCond(thm.getRHS()));
03160             thm = transitivityRule(thm, simplify(thm.getRHS()));
03161             eNew = thm.getRHS();
03162           }
03163         }
03164         else {
03165           thm = d_rules->rewriteLeavesConst(e);
03166           if (thm.isRefl()) {
03167             e.setRewriteNormal();
03168           }
03169           else {
03170             thm = transitivityRule(thm, simplify(thm.getRHS()));
03171           }
03172         }
03173 //         if (!thm.getRHS().isBoolConst()) {
03174 //           e.setRewriteNormal();
03175 //           thm = reflexivityRule(e);
03176 //         }
03177       }
03178       else {
03179         e.setRewriteNormal();
03180         thm = reflexivityRule(e);
03181       }
03182       TRACE("arith", "TheoryArithOld::rewrite[non-literal] => ", thm, " }");
03183       return thm;
03184     }
03185     switch(e.getKind()) {
03186     case EQ:
03187     {
03188       // canonical form for an equality of two leaves
03189       // is just l == r instead of 0 + (-1 * l) + r = 0.
03190       if (isLeaf(e[0]) && isLeaf(e[1]))
03191         thm = reflexivityRule(e);
03192       else { // Otherwise, it is "lhs = 0"
03193         //first convert e to the form 0=e'
03194         if((e[0].isRational() && e[0].getRational() == 0)
03195             || (e[1].isRational() && e[1].getRational() == 0))
03196           //already in 0=e' or e'=0 form
03197           thm = reflexivityRule(e);
03198         else {
03199           thm = d_rules->rightMinusLeft(e);
03200           thm = canonPredEquiv(thm);
03201         }
03202         // Check for trivial equation
03203         if ((thm.getRHS())[0].isRational() && (thm.getRHS())[1].isRational()) {
03204           thm = transitivityRule(thm, d_rules->constPredicate(thm.getRHS()));
03205         } else {
03206           //else equation is non-trivial
03207           thm = normalize(thm);
03208           // Normalization may yield non-simplified terms
03209           if (!thm.getRHS().isBoolConst())
03210             thm = canonPredEquiv(thm);
03211         }
03212       }
03213 
03214       // Equations must be oriented such that lhs >= rhs as Exprs;
03215       // this ordering is given by operator<(Expr,Expr).
03216       const Expr& eq = thm.getRHS();
03217       if(eq.isEq() && eq[0] < eq[1])
03218         thm = transitivityRule(thm, getCommonRules()->rewriteUsingSymmetry(eq));
03219 
03220       // Check if the equation is nonlinear
03221       Expr nonlinearEq = thm.getRHS();
03222       if (nonlinearEq.isEq() && isNonlinearEq(nonlinearEq)) {
03223 
03224         TRACE("arith nonlinear", "nonlinear eq rewrite: ", nonlinearEq, "");
03225 
03226         Expr left = nonlinearEq[0];
03227         Expr right = nonlinearEq[1];
03228 
03229       // Check for multiplicative equations, i.e. x*y = 0
03230       if (isNonlinearSumTerm(left) && right.isRational() && right.getRational() == 0) {
03231         Theorem eq_thm = d_rules->multEqZero(nonlinearEq);
03232         thm = transitivityRule(thm, eq_thm);
03233         thm = transitivityRule(thm, theoryCore()->simplify(thm.getRHS()));
03234         break;
03235       }
03236 
03237       // Heuristics for a sum
03238       if (isPlus(left)) {
03239 
03240           // Search for common factor
03241           if (left[0].getRational() == 0) {
03242             Expr::iterator i = left.begin(), iend = left.end();
03243             ++ i;
03244             set<Expr> factors;
03245             set<Expr>::iterator is, isend;
03246             getFactors(*i, factors);
03247             for (++i; i != iend; ++i) {
03248               set<Expr> factors2;
03249               getFactors(*i, factors2);
03250               for (is = factors.begin(), isend = factors.end(); is != isend;) {
03251                 if (factors2.find(*is) == factors2.end()) {
03252                   factors.erase(is ++);
03253                 } else
03254                   ++ is;
03255               }
03256               if (factors.empty()) break;
03257             }
03258             if (!factors.empty()) {
03259               thm = transitivityRule(thm, d_rules->divideEqnNonConst(left, rat(0), *(factors.begin())));
03260               // got (factor != 0) OR (left / factor = right / factor), need to simplify
03261               thm = transitivityRule(thm, simplify(thm.getRHS()));
03262               TRACE("arith nonlinear", "nonlinear eq rewrite (factoring): ", thm.getRHS(), "");
03263               break;
03264             }
03265           }
03266 
03267           // Look for equal powers (eq in the form of c + pow1 - pow2 = 0)
03268           Rational constant;
03269           Expr power1;
03270           Expr power2;
03271           if (isPowersEquality(nonlinearEq, power1, power2)) {
03272             // Eliminate the powers
03273             thm = transitivityRule(thm, d_rules->elimPower(nonlinearEq));
03274             thm = transitivityRule(thm, simplify(thm.getRHS()));
03275             TRACE("arith nonlinear", "nonlinear eq rewrite (equal powers): ", thm.getRHS(), "");
03276             break;
03277           } else
03278           // Look for one power equality (c - pow = 0);
03279           if (isPowerEquality(nonlinearEq, constant, power1)) {
03280             Rational pow1 = power1[0].getRational();
03281             if (pow1 % 2 == 0 && constant < 0) {
03282               thm = transitivityRule(thm, d_rules->evenPowerEqNegConst(nonlinearEq));
03283               TRACE("arith nonlinear", "nonlinear eq rewrite (even power = negative): ", thm.getRHS(), "");
03284               break;
03285             }
03286             DebugAssert(constant != 0, "Expected nonzero const");
03287             Rational root = ratRoot(constant, pow1.getUnsigned());
03288           if (root != 0) {
03289             thm = transitivityRule(thm, d_rules->elimPowerConst(nonlinearEq, root));
03290             thm = transitivityRule(thm, simplify(thm.getRHS()));
03291             TRACE("arith nonlinear", "nonlinear eq rewrite (rational root): ", thm.getRHS(), "");
03292             break;
03293           } else {
03294             Theorem isIntPower(isIntegerThm(left));
03295             if (!isIntPower.isNull()) {
03296               thm = transitivityRule(thm, d_rules->intEqIrrational(nonlinearEq, isIntPower));
03297               TRACE("arith nonlinear", "nonlinear eq rewrite (irational root): ", thm.getRHS(), "");
03298               break;
03299             }
03300           }
03301           }
03302       }
03303 
03304       // Non-solvable nonlinear equations are rewritten as conjunction of inequalities
03305       if ( (nonlinearEq[0].arity() > 1 && !canPickEqMonomial(nonlinearEq[0])) ||
03306                        (nonlinearEq[1].arity() > 1 && !canPickEqMonomial(nonlinearEq[1])) ) {
03307         thm = transitivityRule(thm, d_rules->eqToIneq(nonlinearEq));
03308         thm = transitivityRule(thm, simplify(thm.getRHS()));
03309         TRACE("arith nonlinear", "nonlinear eq rewrite (not solvable): ", thm.getRHS(), "");
03310         break;
03311       }
03312       }
03313     }
03314     break;
03315     case GRAY_SHADOW:
03316     case DARK_SHADOW:
03317       thm = reflexivityRule(e);
03318       break;
03319     case IS_INTEGER: {
03320       Theorem res(isIntegerDerive(e, typePred(e[0])));
03321       if(!res.isNull())
03322   thm = getCommonRules()->iffTrue(res);
03323       else
03324   thm = reflexivityRule(e);
03325       break;
03326     }
03327     case NOT:
03328       if (!isIneq(e[0]))
03329   //in this case we have "NOT of DARK or GRAY_SHADOW."
03330   thm = reflexivityRule(e);
03331       else {
03332   //In this case we have the "NOT of ineq". get rid of NOT
03333   //and then treat like an ineq
03334   thm = d_rules->negatedInequality(e);
03335   DebugAssert(isGE(thm.getRHS()) || isGT(thm.getRHS()),
03336         "Expected GE or GT");
03337   thm = transitivityRule(thm, d_rules->flipInequality(thm.getRHS()));
03338   thm = transitivityRule(thm, d_rules->rightMinusLeft(thm.getRHS()));
03339   thm = canonPredEquiv(thm);
03340 
03341     // If the inequality is strict and integer, change it to non-strict
03342   Expr theIneq = thm.getRHS();
03343     if(isLT(theIneq)) {
03344       // Check if integer
03345       Theorem isIntLHS(isIntegerThm(theIneq[0]));
03346       Theorem isIntRHS(isIntegerThm(theIneq[1]));
03347       bool isInt = (!isIntLHS.isNull() && !isIntRHS.isNull());
03348           if (isInt) {
03349             thm = canonPredEquiv(
03350               transitivityRule(thm, d_rules->lessThanToLERewrite(theIneq, isIntLHS, isIntRHS, true)));
03351       }
03352     }
03353 
03354   // Check for trivial inequation
03355   if ((thm.getRHS())[1].isRational())
03356     thm = transitivityRule(thm, d_rules->constPredicate(thm.getRHS()));
03357   else {
03358     //else ineq is non-trivial
03359     thm = normalize(thm);
03360     // Normalization may yield non-simplified terms
03361     thm = canonPredEquiv(thm);
03362   }
03363       }
03364       break;
03365     case LT:
03366     case GT:
03367     case LE:
03368     case GE: {
03369 
03370       if (isGE(e) || isGT(e)) {
03371         thm = d_rules->flipInequality(e);
03372         thm = transitivityRule(thm, d_rules->rightMinusLeft(thm.getRHS()));
03373       }
03374       else
03375         thm = d_rules->rightMinusLeft(e);
03376 
03377       thm = canonPredEquiv(thm);
03378 
03379       // If the inequality is strict and integer, change it to non-strict
03380       Expr theIneq = thm.getRHS();
03381       if(isLT(theIneq)) {
03382         // Check if integer
03383         Theorem isIntLHS(isIntegerThm(theIneq[0]));
03384         Theorem isIntRHS(isIntegerThm(theIneq[1]));
03385         bool isInt = (!isIntLHS.isNull() && !isIntRHS.isNull());
03386             if (isInt) {
03387               thm = canonPredEquiv(
03388                 transitivityRule(thm, d_rules->lessThanToLERewrite(theIneq, isIntLHS, isIntRHS, true)));
03389         }
03390       }
03391 
03392       // Check for trivial inequation
03393       if ((thm.getRHS())[1].isRational())
03394         thm = transitivityRule(thm, d_rules->constPredicate(thm.getRHS()));
03395       else { // ineq is non-trivial
03396         thm = normalize(thm);
03397         thm = canonPredEquiv(thm);
03398         if (thm.getRHS()[1].isRational())
03399           thm = transitivityRule(thm, d_rules->constPredicate(thm.getRHS()));
03400       }
03401       break;
03402       }
03403     default:
03404       DebugAssert(false,
03405       "Theory_Arith::rewrite: control should not reach here");
03406       break;
03407     }
03408   }
03409   else {
03410     if (e.isAtomic())
03411       thm = canon(e);
03412     else
03413       thm = reflexivityRule(e);
03414   }
03415   // TODO: this needs to be reviewed, esp for non-linear case
03416   // Arith canonization is idempotent
03417   if (theoryOf(thm.getRHS()) == this)
03418     thm.getRHS().setRewriteNormal();
03419   TRACE("arith", "TheoryArithOld::rewrite => ", thm, " }");
03420   return thm;
03421 }
03422 
03423 
03424 void TheoryArithOld::setup(const Expr& e)
03425 {
03426   if (!e.isTerm()) {
03427     if (e.isNot()) return;
03428     //    if(e.getKind() == IS_INTEGER) {
03429     //      e[0].addToNotify(this, e);
03430     //      return;
03431     //    }
03432     if (isIneq(e)) {
03433       DebugAssert((isLT(e)||isLE(e)) &&
03434                 e[0].isRational() && e[0].getRational() == 0,
03435                 "TheoryArithOld::setup: expected 0 < rhs:" + e.toString());
03436       e[1].addToNotify(this, e);
03437     } else {
03438 //      if (e.isEq()) {
03439 //        // Nonlinear solved equations
03440 //        if (isNonlinearEq(e) && e[0].isRational() && e[0].getRational() == 0)
03441 //          e[0].addToNotify(this, e);
03442 //      }
03443 //
03444 //      DebugAssert(isGrayShadow(e), "TheoryArithOld::setup: expected grayshadow" + e.toString());
03445 //
03446 //      // Do not add the variable, just the subterm e[0].addToNotify(this, e);
03447 //      e[1].addToNotify(this, e);
03448     }
03449     return;
03450   }
03451   int k(0), ar(e.arity());
03452   for ( ; k < ar; ++k) {
03453     e[k].addToNotify(this, e);
03454     TRACE("arith setup", "e["+int2string(k)+"]: ", *(e[k].getNotify()), "");
03455   }
03456 }
03457 
03458 
03459 void TheoryArithOld::update(const Theorem& e, const Expr& d)
03460 {
03461   TRACE("arith update", "update on " + d.toString() + " with ", e.getRHS().toString(), ".");
03462 
03463   if (inconsistent()) return;
03464 
03465   // We accept atoms without find, but only inequalities (they come from the buffer)
03466   DebugAssert(d.hasFind() || isIneq(d), "update on a non-inequality term/atom");
03467 
03468   IF_DEBUG(debugger.counter("arith update total")++;)
03469 //  if (isGrayShadow(d)) {
03470 //    TRACE("shadow update", "updating index of " + d.toString() + " with ", e.getRHS().toString(), ".");
03471 //
03472 //      // Substitute e[1] for e[0] in d and enqueue new shadow
03473 //      DebugAssert(e.getLHS() == d[1], "Mismatch");
03474 //      Theorem thm = find(d);
03475 //
03476 //      //    DebugAssert(thm.getRHS() == trueExpr(), "Expected find = true");
03477 //      vector<unsigned> changed;
03478 //      vector<Theorem> children;
03479 //      changed.push_back(1);
03480 //      children.push_back(e);
03481 //      Theorem thm2 = substitutivityRule(d, changed, children);
03482 //      if (thm.getRHS() == trueExpr()) {
03483 //        enqueueFact(iffMP(getCommonRules()->iffTrueElim(thm), thm2));
03484 //      }
03485 //      else {
03486 //        enqueueFact(getCommonRules()->iffFalseElim(
03487 //          transitivityRule(symmetryRule(thm2), thm)));
03488 //      }
03489 //      IF_DEBUG(debugger.counter("arith update ineq")++;)
03490 //  }
03491 //  else
03492   if (isIneq(d)) {
03493 
03494     // Substitute e[1] for e[0] in d and enqueue new inequality
03495     DebugAssert(e.getLHS() == d[1], "Mismatch");
03496     Theorem thm;
03497     if (d.hasFind()) thm = find(d);
03498 
03499 //    bool diff_logic = false;
03500 //    Expr new_rhs = e.getRHS();
03501 //    if (!isPlus(new_rhs)) {
03502 //      if (isLeaf(new_rhs)) diff_logic = true;
03503 //    }
03504 //    else {
03505 //      int arity = new_rhs.arity();
03506 //      if (arity == 2)  {
03507 //        if (new_rhs[0].isRational()) diff_logic = true;
03508 //        else {
03509 //          Expr ax = new_rhs[0], a, x;
03510 //          Expr by = new_rhs[1], b, y;
03511 //          separateMonomial(ax, a, x);
03512 //          separateMonomial(by, b, y);
03513 //          if ((a.getRational() == 1 && b.getRational() == -1) ||
03514 //              (a.getRational() == -1 && b.getRational() == 1))
03515 //            diff_logic = true;
03516 //        }
03517 //      } else {
03518 //        if (arity == 3 && new_rhs[0].isRational()) {
03519 //          Expr ax = new_rhs[1], a, x;
03520 //          Expr by = new_rhs[2], b, y;
03521 //          separateMonomial(ax, a, x);
03522 //          separateMonomial(by, b, y);
03523 //          if ((a.getRational() == 1 && b.getRational() == -1) ||
03524 //              (a.getRational() == -1 && b.getRational() == 1))
03525 //                  diff_logic = true;
03526 //        }
03527 //      }
03528 //    }
03529 
03530     //    DebugAssert(thm.getRHS() == trueExpr(), "Expected find = true");
03531     vector<unsigned> changed;
03532     vector<Theorem> children;
03533     changed.push_back(1);
03534     children.push_back(e);
03535     Theorem thm2 = substitutivityRule(d, changed, children);
03536     Expr newIneq = thm2.getRHS();
03537 
03538     // If this inequality is bufferred but not yet projected, just wait for it
03539     // but don't add the find to the buffer as it will be projected as a find
03540     // We DO want it to pass through all the buffer stuff but NOT get into the buffer
03541     // NOTE: this means that the difference logic WILL get processed
03542     if ((thm.isNull() || thm.getRHS() != falseExpr()) &&
03543         bufferedInequalities.find(d) != bufferedInequalities.end() &&
03544         alreadyProjected.find(d) == alreadyProjected.end()) {
03545       TRACE("arith update", "simplified but not projected : ", thm2.getRHS(), "");
03546       dontBuffer[thm2.getRHS()] = true;
03547     }
03548 
03549     if (thm.isNull()) {
03550       // This hy is in the buffer, not in the core
03551       // if it has been projected, than it's parent has been projected and will get reprojected
03552       // accuratlz. If it has not been projected, we don't care it's still there
03553       TRACE("arith update", "in udpate, but no find", "", "");
03554       if (bufferedInequalities.find(d) != bufferedInequalities.end()) {
03555         if (thm2.getRHS()[1].isRational()) enqueueFact(iffMP(bufferedInequalities[d], thm2));
03556         else if (alreadyProjected.find(d) != alreadyProjected.end()) {
03557           // the parent will get reprojected
03558           alreadyProjected[d] = d;
03559         }
03560       }
03561     }
03562     else if (thm.getRHS() == trueExpr()) {
03563       if (!newIneq[1].isRational() || newIneq[1].getRational() <= 0)
03564         enqueueFact(iffMP(getCommonRules()->iffTrueElim(thm), thm2));
03565     }
03566     else {
03567       enqueueFact(getCommonRules()->iffFalseElim(
03568         transitivityRule(symmetryRule(thm2), thm)));
03569     }
03570     IF_DEBUG(debugger.counter("arith update ineq")++;)
03571   }
03572   else if (d.isEq()) {
03573     TRACE("arith nonlinear", "TheoryArithOld::update() on equality ", d, "");
03574     // We get equalitites from the non-solve nonlinear equations
03575     // only the right hand sides get updated
03576     vector<unsigned> changed;
03577     vector<Theorem> children;
03578     changed.push_back(0);
03579     children.push_back(e);
03580     Theorem thm = substitutivityRule(d, changed, children);
03581     Expr newEq = thm.getRHS();
03582 
03583     Theorem d_find = find(d);
03584     if (d_find.getRHS() == trueExpr()) enqueueFact(iffMP(getCommonRules()->iffTrueElim(d_find), thm));
03585       else enqueueFact(getCommonRules()->iffFalseElim(transitivityRule(symmetryRule(thm), d_find)));
03586   }
03587   else if (d.getKind() == IS_INTEGER) {
03588     // This should only happen if !d has been asserted
03589     DebugAssert(e.getRHS() == findExpr(d[0]), "Unexpected");
03590     if (isInteger(e.getRHS())) {
03591       Theorem thm = substitutivityRule(d, find(d[0]));
03592       thm = transitivityRule(symmetryRule(find(d)), thm);
03593       thm = iffMP(thm, simplify(thm.getExpr()));
03594       setInconsistent(thm);
03595     }
03596     else {
03597       e.getRHS().addToNotify(this, d);
03598     }
03599   }
03600   else if (find(d).getRHS() == d) {
03601 //     Theorem thm = canonSimp(d);
03602 //     TRACE("arith", "TheoryArithOld::update(): thm = ", thm, "");
03603 //     DebugAssert(leavesAreSimp(thm.getRHS()), "updateHelper error: "
03604 //      +thm.getExpr().toString());
03605 //     assertEqualities(transitivityRule(thm, rewrite(thm.getRHS())));
03606 //     IF_DEBUG(debugger.counter("arith update find(d)=d")++;)
03607     Theorem thm = simplify(d);
03608     // If the original is was a shared term, add this one as as a shared term also
03609     if (d_sharedTerms.find(d) != d_sharedTerms.end()) addSharedTerm(thm.getRHS());
03610     DebugAssert(thm.getRHS().isAtomic(), "Expected atomic");
03611     assertEqualities(thm);
03612   }
03613 }
03614 
03615 
03616 Theorem TheoryArithOld::solve(const Theorem& thm)
03617 {
03618   DebugAssert(thm.isRewrite() && thm.getLHS().isTerm(), "");
03619   const Expr& lhs = thm.getLHS();
03620   const Expr& rhs = thm.getRHS();
03621 
03622   // Check for already solved equalities.
03623 
03624   // Have to be careful about the types: integer variable cannot be
03625   // assigned a real term.  Also, watch for e[0] being a subexpression
03626   // of e[1]: this would create an unsimplifiable expression.
03627   if (isLeaf(lhs) && !isLeafIn(lhs, rhs)
03628       && (!isInteger(lhs) || isInteger(rhs))
03629       // && !e[0].subExprOf(e[1])
03630       )
03631     return thm;
03632 
03633   // Symmetric version is already solved
03634   if (isLeaf(rhs) && !isLeafIn(rhs, lhs)
03635       && (!isInteger(rhs) || isInteger(lhs))
03636       // && !e[1].subExprOf(e[0])
03637       )
03638     return symmetryRule(thm);
03639 
03640   return doSolve(thm);
03641 }
03642 
03643 
03644 void TheoryArithOld::computeModelTerm(const Expr& e, std::vector<Expr>& v) {
03645   switch(e.getKind()) {
03646   case RATIONAL_EXPR: // Skip the constants
03647     break;
03648   case PLUS:
03649   case MULT:
03650   case DIVIDE:
03651   case POW: // This is not a variable; extract the variables from children
03652     for(Expr::iterator i=e.begin(), iend=e.end(); i!=iend; ++i)
03653       // getModelTerm(*i, v);
03654       v.push_back(*i);
03655     break;
03656   default: { // Otherwise it's a variable.  Check if it has a find pointer
03657     Expr e2(findExpr(e));
03658     if(e==e2) {
03659       TRACE("model", "TheoryArithOld::computeModelTerm(", e, "): a variable");
03660       // Leave it alone (it has no descendants)
03661       // v.push_back(e);
03662     } else {
03663       TRACE("model", "TheoryArithOld::computeModelTerm("+e.toString()
03664       +"): has find pointer to ", e2, "");
03665       v.push_back(e2);
03666     }
03667   }
03668   }
03669 }
03670 
03671 
03672 Expr TheoryArithOld::computeTypePred(const Type& t, const Expr& e) {
03673   Expr tExpr = t.getExpr();
03674   switch(tExpr.getKind()) {
03675   case INT:
03676     return Expr(IS_INTEGER, e);
03677   case SUBRANGE: {
03678     std::vector<Expr> kids;
03679     kids.push_back(Expr(IS_INTEGER, e));
03680     kids.push_back(leExpr(tExpr[0], e));
03681     kids.push_back(leExpr(e, tExpr[1]));
03682     return andExpr(kids);
03683   }
03684   default:
03685     return e.getEM()->trueExpr();
03686   }
03687 }
03688 
03689 
03690 void TheoryArithOld::checkAssertEqInvariant(const Theorem& e)
03691 {
03692   if (e.isRewrite()) {
03693     DebugAssert(e.getLHS().isTerm(), "Expected equation");
03694     if (isLeaf(e.getLHS())) {
03695       // should be in solved form
03696       DebugAssert(!isLeafIn(e.getLHS(),e.getRHS()),
03697                   "Not in solved form: lhs appears in rhs");
03698     }
03699     else {
03700       DebugAssert(e.getLHS().hasFind(), "Expected lhs to have find");
03701       DebugAssert(!leavesAreSimp(e.getLHS()),
03702                   "Expected at least one unsimplified leaf on lhs");
03703     }
03704     DebugAssert(canonSimp(e.getRHS()).getRHS() == e.getRHS(),
03705                 "Expected canonSimp(rhs) = canonSimp(rhs)");
03706   }
03707   else {
03708     Expr expr = e.getExpr();
03709     if (expr.isFalse()) return;
03710 
03711     vector<Theorem> eqs;
03712     Theorem thm;
03713     int index, index2;
03714 
03715     for (index = 0; index < expr.arity(); ++index) {
03716       thm = getCommonRules()->andElim(e, index);
03717       eqs.push_back(thm);
03718       if (thm.getExpr().isFalse()) return;
03719       DebugAssert(eqs[index].isRewrite() &&
03720                   eqs[index].getLHS().isTerm(), "Expected equation");
03721     }
03722 
03723     // Check for solved form
03724     for (index = 0; index < expr.arity(); ++index) {
03725       DebugAssert(isLeaf(eqs[index].getLHS()), "expected leaf on lhs");
03726       DebugAssert(canonSimp(eqs[index].getRHS()).getRHS() == eqs[index].getRHS(),
03727                   "Expected canonSimp(rhs) = canonSimp(rhs)");
03728       DebugAssert(recursiveCanonSimpCheck(eqs[index].getRHS()),
03729                   "Failed recursive canonSimp check");
03730       for (index2 = 0; index2 < expr.arity(); ++index2) {
03731         DebugAssert(index == index2 ||
03732                     eqs[index].getLHS() != eqs[index2].getLHS(),
03733                     "Not in solved form: repeated lhs");
03734         DebugAssert(!isLeafIn(eqs[index].getLHS(),eqs[index2].getRHS()),
03735                     "Not in solved form: lhs appears in rhs");
03736       }
03737     }
03738   }
03739 }
03740 
03741 
03742 void TheoryArithOld::checkType(const Expr& e)
03743 {
03744   switch (e.getKind()) {
03745     case INT:
03746     case REAL:
03747       if (e.arity() > 0) {
03748         throw Exception("Ill-formed arithmetic type: "+e.toString());
03749       }
03750       break;
03751     case SUBRANGE:
03752       if (e.arity() != 2 ||
03753           !isIntegerConst(e[0]) ||
03754           !isIntegerConst(e[1]) ||
03755           e[0].getRational() > e[1].getRational()) {
03756         throw Exception("bad SUBRANGE type expression"+e.toString());
03757       }
03758       break;
03759     default:
03760       DebugAssert(false, "Unexpected kind in TheoryArithOld::checkType"
03761                   +getEM()->getKindName(e.getKind()));
03762   }
03763 }
03764 
03765 
03766 Cardinality TheoryArithOld::finiteTypeInfo(Expr& e, Unsigned& n,
03767                                            bool enumerate, bool computeSize)
03768 {
03769   Cardinality card = CARD_INFINITE;
03770   switch (e.getKind()) {
03771     case SUBRANGE: {
03772       card = CARD_FINITE;
03773       Expr typeExpr = e;
03774       if (enumerate) {
03775         Rational r = typeExpr[0].getRational() + n;
03776         if (r <= typeExpr[1].getRational()) {
03777           e = rat(r);
03778         }
03779         else e = Expr();
03780       }
03781       if (computeSize) {
03782         Rational r = typeExpr[1].getRational() - typeExpr[0].getRational() + 1;
03783         n = r.getUnsigned();
03784       }
03785       break;
03786     }
03787     default:
03788       break;
03789   }
03790   return card;
03791 }
03792 
03793 
03794 void TheoryArithOld::computeType(const Expr& e)
03795 {
03796   switch (e.getKind()) {
03797     case REAL_CONST:
03798       e.setType(d_realType);
03799       break;
03800     case RATIONAL_EXPR:
03801       if(e.getRational().isInteger())
03802         e.setType(d_intType);
03803       else
03804         e.setType(d_realType);
03805       break;
03806     case UMINUS:
03807     case PLUS:
03808     case MINUS:
03809     case MULT:
03810     case POW: {
03811       bool isInt = true;
03812       for(int k = 0; k < e.arity(); ++k) {
03813         if(d_realType != getBaseType(e[k]))
03814           throw TypecheckException("Expecting type REAL with `" +
03815                                    getEM()->getKindName(e.getKind()) + "',\n"+
03816                                    "but got a " + getBaseType(e[k]).toString()+
03817                                    " for:\n" + e.toString());
03818         if(isInt && !isInteger(e[k]))
03819           isInt = false;
03820       }
03821       if(isInt)
03822         e.setType(d_intType);
03823       else
03824         e.setType(d_realType);
03825       break;
03826     }
03827     case DIVIDE: {
03828       Expr numerator = e[0];
03829       Expr denominator = e[1];
03830       if (getBaseType(numerator) != d_realType ||
03831           getBaseType(denominator) != d_realType) {
03832         throw TypecheckException("Expecting only REAL types with `DIVIDE',\n"
03833                                  "but got " + getBaseType(numerator).toString()+
03834                                  " and " + getBaseType(denominator).toString() +
03835                                  " for:\n" + e.toString());
03836       }
03837       if(denominator.isRational() && 1 == denominator.getRational())
03838         e.setType(numerator.getType());
03839       else
03840         e.setType(d_realType);
03841       break;
03842     }
03843     case LT:
03844     case LE:
03845     case GT:
03846     case GE:
03847     case GRAY_SHADOW:
03848       // Need to know types for all exprs -Clark
03849       //    e.setType(boolType());
03850       //    break;
03851     case DARK_SHADOW:
03852       for (int k = 0; k < e.arity(); ++k) {
03853         if (d_realType != getBaseType(e[k]))
03854           throw TypecheckException("Expecting type REAL with `" +
03855                                    getEM()->getKindName(e.getKind()) + "',\n"+
03856                                    "but got a " + getBaseType(e[k]).toString()+
03857                                    " for:\n" + e.toString());
03858       }
03859 
03860       e.setType(boolType());
03861       break;
03862     case IS_INTEGER:
03863       if(d_realType != getBaseType(e[0]))
03864         throw TypecheckException("Expected type REAL, but got "
03865                                  +getBaseType(e[0]).toString()
03866                                  +"\n\nExpr = "+e.toString());
03867       e.setType(boolType());
03868       break;
03869     default:
03870       DebugAssert(false,"TheoryArithOld::computeType: unexpected expression:\n "
03871                   +e.toString());
03872       break;
03873   }
03874 }
03875 
03876 
03877 Type TheoryArithOld::computeBaseType(const Type& t) {
03878   IF_DEBUG(int kind = t.getExpr().getKind();)
03879   DebugAssert(kind==INT || kind==REAL || kind==SUBRANGE,
03880         "TheoryArithOld::computeBaseType("+t.toString()+")");
03881   return realType();
03882 }
03883 
03884 
03885 Expr
03886 TheoryArithOld::computeTCC(const Expr& e) {
03887   Expr tcc(Theory::computeTCC(e));
03888   switch(e.getKind()) {
03889   case DIVIDE:
03890     DebugAssert(e.arity() == 2, "");
03891     return tcc.andExpr(!(e[1].eqExpr(rat(0))));
03892   default:
03893     return tcc;
03894   }
03895 }
03896 
03897 ///////////////////////////////////////////////////////////////////////////////
03898 //parseExprOp:
03899 //translating special Exprs to regular EXPR??
03900 ///////////////////////////////////////////////////////////////////////////////
03901 Expr
03902 TheoryArithOld::parseExprOp(const Expr& e) {
03903   //TRACE("parser", "TheoryArithOld::parseExprOp(", e, ")");
03904   //std::cout << "Were here";
03905   // If the expression is not a list, it must have been already
03906   // parsed, so just return it as is.
03907   switch(e.getKind()) {
03908   case ID: {
03909     int kind = getEM()->getKind(e[0].getString());
03910     switch(kind) {
03911     case NULL_KIND: return e; // nothing to do
03912     case REAL:
03913     case INT:
03914     case NEGINF:
03915     case POSINF: return getEM()->newLeafExpr(kind);
03916     default:
03917       DebugAssert(false, "Bad use of bare keyword: "+e.toString());
03918       return e;
03919     }
03920   }
03921   case RAW_LIST: break; // break out of switch, do the hard work
03922   default:
03923     return e;
03924   }
03925 
03926   DebugAssert(e.getKind() == RAW_LIST && e.arity() > 0,
03927         "TheoryArithOld::parseExprOp:\n e = "+e.toString());
03928 
03929   const Expr& c1 = e[0][0];
03930   int kind = getEM()->getKind(c1.getString());
03931   switch(kind) {
03932     case UMINUS: {
03933       if(e.arity() != 2)
03934   throw ParserException("UMINUS requires exactly one argument: "
03935       +e.toString());
03936       return uminusExpr(parseExpr(e[1]));
03937     }
03938     case PLUS: {
03939       vector<Expr> k;
03940       Expr::iterator i = e.begin(), iend=e.end();
03941       // Skip first element of the vector of kids in 'e'.
03942       // The first element is the operator.
03943       ++i;
03944       // Parse the kids of e and push them into the vector 'k'
03945       for(; i!=iend; ++i) k.push_back(parseExpr(*i));
03946       return plusExpr(k);
03947     }
03948     case MINUS: {
03949       if(e.arity() == 2) {
03950         if (false && (getEM()->getInputLang() == SMTLIB_LANG
03951                       || getEM()->getInputLang() == SMTLIB_V2_LANG)) {
03952           throw ParserException("Unary Minus should use '~' instead of '-' in SMT-LIB expr:"
03953                                 +e.toString());
03954         }
03955         else {
03956           return uminusExpr(parseExpr(e[1]));
03957         }
03958       }
03959       else if(e.arity() == 3)
03960   return minusExpr(parseExpr(e[1]), parseExpr(e[2]));
03961       else
03962   throw ParserException("MINUS requires one or two arguments:"
03963       +e.toString());
03964     }
03965     case MULT: {
03966       vector<Expr> k;
03967       Expr::iterator i = e.begin(), iend=e.end();
03968       // Skip first element of the vector of kids in 'e'.
03969       // The first element is the operator.
03970       ++i;
03971       // Parse the kids of e and push them into the vector 'k'
03972       for(; i!=iend; ++i) k.push_back(parseExpr(*i));
03973       return multExpr(k);
03974     }
03975     case POW: {
03976       return powExpr(parseExpr(e[1]), parseExpr(e[2]));
03977     }
03978     case DIVIDE:
03979       { return divideExpr(parseExpr(e[1]), parseExpr(e[2]));  }
03980     case LT:
03981       { return ltExpr(parseExpr(e[1]), parseExpr(e[2]));  }
03982     case LE:
03983       { return leExpr(parseExpr(e[1]), parseExpr(e[2]));  }
03984     case GT:
03985       { return gtExpr(parseExpr(e[1]), parseExpr(e[2]));  }
03986     case GE:
03987       { return geExpr(parseExpr(e[1]), parseExpr(e[2]));  }
03988     case INTDIV:
03989     case MOD:
03990     case SUBRANGE: {
03991       vector<Expr> k;
03992       Expr::iterator i = e.begin(), iend=e.end();
03993       // Skip first element of the vector of kids in 'e'.
03994       // The first element is the operator.
03995       ++i;
03996       // Parse the kids of e and push them into the vector 'k'
03997       for(; i!=iend; ++i)
03998         k.push_back(parseExpr(*i));
03999       return Expr(kind, k, e.getEM());
04000     }
04001     case IS_INTEGER: {
04002       if(e.arity() != 2)
04003   throw ParserException("IS_INTEGER requires exactly one argument: "
04004       +e.toString());
04005       return Expr(IS_INTEGER, parseExpr(e[1]));
04006     }
04007     default:
04008       DebugAssert(false,
04009         "TheoryArithOld::parseExprOp: invalid input " + e.toString());
04010       break;
04011   }
04012   return e;
04013 }
04014 
04015 ///////////////////////////////////////////////////////////////////////////////
04016 // Pretty-printing                                                           //
04017 ///////////////////////////////////////////////////////////////////////////////
04018 
04019 
04020 ExprStream&
04021 TheoryArithOld::print(ExprStream& os, const Expr& e) {
04022   switch(os.lang()) {
04023     case SIMPLIFY_LANG:
04024       switch(e.getKind()) {
04025       case RATIONAL_EXPR:
04026   e.print(os);
04027   break;
04028       case SUBRANGE:
04029   os <<"ERROR:SUBRANGE:not supported in Simplify\n";
04030   break;
04031       case IS_INTEGER:
04032   os <<"ERROR:IS_INTEGER:not supported in Simplify\n";
04033   break;
04034       case PLUS:  {
04035   int i=0, iend=e.arity();
04036   os << "(+ ";
04037   if(i!=iend) os << e[i];
04038   ++i;
04039   for(; i!=iend; ++i) os << " " << e[i];
04040   os <<  ")";
04041   break;
04042       }
04043       case MINUS:
04044   os << "(- " << e[0] << " " << e[1]<< ")";
04045   break;
04046       case UMINUS:
04047   os << "-" << e[0] ;
04048   break;
04049       case MULT:  {
04050   int i=0, iend=e.arity();
04051   os << "(* " ;
04052   if(i!=iend) os << e[i];
04053   ++i;
04054   for(; i!=iend; ++i) os << " " << e[i];
04055   os <<  ")";
04056   break;
04057       }
04058       case POW:
04059           os << "(" << push << e[1] << space << "^ " << e[0] << push << ")";
04060           break;
04061       case DIVIDE:
04062   os << "(" << push << e[0] << space << "/ " << e[1] << push << ")";
04063   break;
04064       case LT:
04065   if (isInt(e[0].getType()) || isInt(e[1].getType())) {
04066   }
04067   os << "(< " << e[0] << " " << e[1] <<")";
04068   break;
04069       case LE:
04070           os << "(<= " << e[0]  << " " << e[1] << ")";
04071           break;
04072       case GT:
04073   os << "(> " << e[0] << " " << e[1] << ")";
04074   break;
04075       case GE:
04076   os << "(>= " << e[0] << " " << e[1]  << ")";
04077   break;
04078       case DARK_SHADOW:
04079       case GRAY_SHADOW:
04080   os <<"ERROR:SHADOW:not supported in Simplify\n";
04081   break;
04082       default:
04083   // Print the top node in the default LISP format, continue with
04084   // pretty-printing for children.
04085           e.print(os);
04086 
04087           break;
04088       }
04089       break; // end of case SIMPLIFY_LANG
04090 
04091     case TPTP_LANG:
04092       switch(e.getKind()) {
04093       case RATIONAL_EXPR:
04094   e.print(os);
04095   break;
04096       case SUBRANGE:
04097   os <<"ERROR:SUBRANGE:not supported in TPTP\n";
04098   break;
04099       case IS_INTEGER:
04100   os <<"ERROR:IS_INTEGER:not supported in TPTP\n";
04101   break;
04102       case PLUS:  {
04103   if(!isInteger(e[0])){
04104     os<<"ERRPR:plus only supports inteters now in TPTP\n";
04105     break;
04106   }
04107 
04108   int i=0, iend=e.arity();
04109   if(iend <=1){
04110     os<<"ERROR,plus must have more than two numbers in TPTP\n";
04111     break;
04112   }
04113 
04114   for(i=0; i <= iend-2; ++i){
04115     os << "$plus_int(";
04116     os << e[i] << ",";
04117   }
04118 
04119   os<< e[iend-1];
04120 
04121   for(i=0 ; i <= iend-2; ++i){
04122     os << ")";
04123   }
04124 
04125   break;
04126       }
04127       case MINUS:
04128   if(!isInteger(e[0])){
04129     os<<"ERRPR:arithmetic operations only support inteters now in TPTP\n";
04130     break;
04131   }
04132 
04133   os << "$minus_int(" << e[0] << "," << e[1]<< ")";
04134   break;
04135       case UMINUS:
04136   if(!isInteger(e[0])){
04137     os<<"ERRPR:arithmetic operations only support inteters now in TPTP\n";
04138     break;
04139   }
04140 
04141   os << "$uminus_int(" << e[0] <<")" ;
04142   break;
04143       case MULT:  {
04144   if(!isInteger(e[0])){
04145     os<<"ERRPR:times only supports inteters now in TPTP\n";
04146     break;
04147   }
04148 
04149   int i=0, iend=e.arity();
04150   if(iend <=1){
04151     os<<"ERROR:times must have more than two numbers in TPTP\n";
04152     break;
04153   }
04154 
04155   for(i=0; i <= iend-2; ++i){
04156     os << "$times_int(";
04157     os << e[i] << ",";
04158   }
04159 
04160   os<< e[iend-1];
04161 
04162   for(i=0 ; i <= iend-2; ++i){
04163     os << ")";
04164   }
04165 
04166   break;
04167       }
04168       case POW:
04169 
04170   if(!isInteger(e[0])){
04171     os<<"ERRPR:arithmetic operations only support inteters now in TPTP\n";
04172     break;
04173   }
04174 
04175   os << "$power_int(" << push << e[1] << space << "^ " << e[0] << push << ")";
04176   break;
04177 
04178       case DIVIDE:
04179   if(!isInteger(e[0])){
04180     os<<"ERRPR:arithmetic operations only support inteters now in TPTP\n";
04181     break;
04182   }
04183 
04184   os << "divide_int(" <<e[0]  << "," << e[1] << ")";
04185   break;
04186 
04187       case LT:
04188   if(!isInteger(e[0])){
04189     os<<"ERRPR:arithmetic operations only support inteters now in TPTP\n";
04190     break;
04191   }
04192   os << "$less_int(" << e[0] << "," << e[1] <<")";
04193   break;
04194 
04195       case LE:
04196   if(!isInteger(e[0])){
04197     os<<"ERRPR:arithmetic operations only support inteters now in TPTP\n";
04198     break;
04199   }
04200 
04201           os << "$lesseq_int(" << e[0]  << "," << e[1] << ")";
04202           break;
04203 
04204       case GT:
04205   if(!isInteger(e[0])){
04206     os<<"ERRPR:arithmetic operations only support inteters now in TPTP\n";
04207     break;
04208   }
04209 
04210   os << "$greater_int(" << e[0] << "," << e[1] << ")";
04211   break;
04212 
04213       case GE:
04214   if(!isInteger(e[0])){
04215     os<<"ERRPR:arithmetic operations only support inteters now in TPTP\n";
04216     break;
04217   }
04218 
04219   os << "$greatereq_int(" << e[0] << "," << e[1]  << ")";
04220   break;
04221       case DARK_SHADOW:
04222       case GRAY_SHADOW:
04223   os <<"ERROR:SHADOW:not supported in TPTP\n";
04224   break;
04225 
04226       case INT:
04227   os <<"$int";
04228   break;
04229       case REAL:
04230   os <<"ERROR:REAL not supported in TPTP\n";
04231       default:
04232   // Print the top node in the default LISP format, continue with
04233   // pretty-printing for children.
04234   e.print(os);
04235 
04236           break;
04237       }
04238       break; // end of case TPTP_LANG
04239 
04240     case PRESENTATION_LANG:
04241       switch(e.getKind()) {
04242         case REAL:
04243           os << "REAL";
04244           break;
04245         case INT:
04246           os << "INT";
04247           break;
04248         case RATIONAL_EXPR:
04249           e.print(os);
04250           break;
04251         case NEGINF:
04252           os << "NEGINF";
04253           break;
04254         case POSINF:
04255           os << "POSINF";
04256           break;
04257         case SUBRANGE:
04258           if(e.arity() != 2) e.printAST(os);
04259           else
04260             os << "[" << push << e[0] << ".." << e[1] << push << "]";
04261           break;
04262         case IS_INTEGER:
04263     if(e.arity() == 1)
04264       os << "IS_INTEGER(" << push << e[0] << push << ")";
04265     else
04266       e.printAST(os);
04267     break;
04268         case PLUS:  {
04269           int i=0, iend=e.arity();
04270           os << "(" << push;
04271           if(i!=iend) os << e[i];
04272           ++i;
04273           for(; i!=iend; ++i) os << space << "+ " << e[i];
04274           os << push << ")";
04275           break;
04276         }
04277         case MINUS:
04278           os << "(" << push << e[0] << space << "- " << e[1] << push << ")";
04279           break;
04280         case UMINUS:
04281           os << "-(" << push << e[0] << push << ")";
04282           break;
04283         case MULT:  {
04284           int i=0, iend=e.arity();
04285           os << "(" << push;
04286           if(i!=iend) os << e[i];
04287           ++i;
04288           for(; i!=iend; ++i) os << space << "* " << e[i];
04289           os << push << ")";
04290           break;
04291         }
04292         case POW:
04293           os << "(" << push << e[1] << space << "^ " << e[0] << push << ")";
04294           break;
04295         case DIVIDE:
04296           os << "(" << push << e[0] << space << "/ " << e[1] << push << ")";
04297           break;
04298         case LT:
04299           if (isInt(e[0].getType()) || isInt(e[1].getType())) {
04300           }
04301           os << "(" << push << e[0] << space << "< " << e[1] << push << ")";
04302           break;
04303         case LE:
04304           os << "(" << push << e[0] << space << "<= " << e[1] << push << ")";
04305           break;
04306         case GT:
04307           os << "(" << push << e[0] << space << "> " << e[1] << push << ")";
04308           break;
04309         case GE:
04310           os << "(" << push << e[0] << space << ">= " << e[1] << push << ")";
04311           break;
04312         case DARK_SHADOW:
04313     os << "DARK_SHADOW(" << push << e[0] << ", " << space << e[1] << push << ")";
04314     break;
04315         case GRAY_SHADOW:
04316     os << "GRAY_SHADOW(" << push << e[0] << ","  << space << e[1]
04317        << "," << space << e[2] << "," << space << e[3] << push << ")";
04318     break;
04319         default:
04320           // Print the top node in the default LISP format, continue with
04321           // pretty-printing for children.
04322           e.printAST(os);
04323 
04324           break;
04325       }
04326       break; // end of case PRESENTATION_LANG
04327  case SPASS_LANG: {
04328       switch(e.getKind()) {
04329         case REAL_CONST:
04330           printRational(os, e[0].getRational(), true);
04331           break;
04332         case RATIONAL_EXPR:
04333           printRational(os, e.getRational());
04334           break;
04335         case REAL:
04336           throw SmtlibException("TheoryArithOld::print: SPASS: REAL not implemented");
04337           break;
04338         case INT:
04339           throw SmtlibException("TheoryArithOld::print: SPASS: INT not implemented");
04340           break;
04341         case SUBRANGE:
04342           throw SmtlibException("TheoryArithOld::print: SPASS: SUBRANGE not implemented");
04343           break;
04344         case IS_INTEGER:
04345           throw SmtlibException("TheoryArithOld::print: SPASS: IS_INTEGER not implemented");
04346         case PLUS: {
04347     int arity = e.arity();
04348     if(2 == arity) {
04349       os << push << "plus("
04350                << e[0] << "," << space << e[1]
04351                << push << ")";
04352     }
04353     else if(2 < arity) {
04354       for (int i = 0 ; i < arity - 2; i++){
04355         os << push << "plus(";
04356         os << e[i] << "," << space;
04357       }
04358       os << push << "plus("
04359                << e[arity - 2] << "," << space << e[arity - 1]
04360                << push << ")";
04361       for (int i = 0 ; i < arity - 2; i++){
04362         os << push << ")";
04363       }
04364     }
04365     else {
04366       throw SmtlibException("TheoryArithOld::print: SPASS: Less than two arguments for plus");
04367     }
04368           break;
04369         }
04370         case MINUS: {
04371           os << push << "plus(" << e[0]
04372              << "," << space << push << "mult(-1,"
04373              << space << e[1] << push << ")" << push << ")";
04374           break;
04375         }
04376         case UMINUS: {
04377           os << push << "plus(0,"
04378              << space << push << "mult(-1,"
04379              << space << e[0] << push << ")" << push << ")";
04380           break;
04381         }
04382         case MULT: {
04383     int arity = e.arity();
04384     if (2 == arity){
04385       os << push << "mult("
04386                << e[0] << "," << space << e[1]
04387                << push << ")";
04388     }
04389     else if (2 < arity){
04390       for (int i = 0 ; i < arity - 2; i++){
04391         os << push << "mult(";
04392         os << e[i] << "," << space;
04393       }
04394       os << push << "mult("
04395                << e[arity - 2] << "," << space << e[arity - 1]
04396                << push << ")";
04397       for (int i = 0 ; i < arity - 2; i++){
04398         os << push << ")";
04399       }
04400     }
04401     else{
04402       throw SmtlibException("TheoryArithOld::print: SPASS: Less than two arguments for mult");
04403     }
04404           break;
04405         }
04406         case POW:
04407           if (e[0].isRational() && e[0].getRational().isInteger()) {
04408             int i=0, iend=e[0].getRational().getInt();
04409               for(; i!=iend; ++i) {
04410                 if (i < iend-2) {
04411                   os << push << "mult(";
04412                 }
04413                 os << e[1] << "," << space;
04414               }
04415         os << push << "mult("
04416                  << e[1] << "," << space << e[1];
04417               for (i=0; i < iend-1; ++i) {
04418                 os << push << ")";
04419               }
04420           }
04421           else {
04422             throw SmtlibException("TheoryArithOld::print: SPASS: POW not supported: " + e.toString(PRESENTATION_LANG));
04423           }
04424           break;
04425         case DIVIDE: {
04426     os << "ERROR "<< endl;break;
04427           throw SmtlibException("TheoryArithOld::print: SPASS: unexpected use of DIVIDE");
04428           break;
04429         }
04430         case LT: {
04431           Rational r;
04432           os << push << "ls(" << space;
04433           os << e[0] << "," << space << e[1] << push << ")";
04434           break;
04435         }
04436         case LE: {
04437           Rational r;
04438           os << push << "le(" << space;
04439           os << e[0] << "," << space << e[1] << push << ")";
04440           break;
04441         }
04442         case GT: {
04443           Rational r;
04444           os << push << "gs(" << space;
04445           os << e[0] << "," << space << e[1] << push << ")";
04446           break;
04447         }
04448         case GE: {
04449           Rational r;
04450           os << push << "ge(" << space;
04451           os << e[0] << "," << space << e[1] << push << ")";
04452           break;
04453         }
04454 
04455         default:
04456           throw SmtlibException("TheoryArithOld::print: SPASS: default not supported");
04457       }
04458       break; // end of case SPASS_LANG
04459     }
04460     case SMTLIB_LANG:
04461     case SMTLIB_V2_LANG: {
04462       switch(e.getKind()) {
04463         case REAL_CONST:
04464           printRational(os, e[0].getRational(), true);
04465           break;
04466         case RATIONAL_EXPR:
04467           printRational(os, e.getRational());
04468           break;
04469         case REAL:
04470           os << "Real";
04471           break;
04472         case INT:
04473           os << "Int";
04474           break;
04475         case SUBRANGE:
04476           throw SmtlibException("TheoryArithOld::print: SMTLIB: SUBRANGE not implemented");
04477 //           if(e.arity() != 2) e.print(os);
04478 //           else
04479 //             os << "(" << push << "SUBRANGE" << space << e[0]
04480 //         << space << e[1] << push << ")";
04481           break;
04482         case IS_INTEGER:
04483     if(e.arity() == 1) {
04484             if (os.lang() == SMTLIB_LANG) {
04485               os << "(" << push << "IsInt" << space << e[0] << push << ")";
04486             }
04487             else {
04488               os << "(" << push << "is_int" << space << e[0] << push << ")";
04489             }
04490           }
04491     else
04492             throw SmtlibException("TheoryArithOld::print: SMTLIB: IS_INTEGER used unexpectedly");
04493     break;
04494         case PLUS:  {
04495           if(e.arity() == 1 && os.lang() == SMTLIB_V2_LANG) {
04496             os << e[0];
04497           } else {
04498             os << "(" << push << "+";
04499             Expr::iterator i = e.begin(), iend = e.end();
04500             for(; i!=iend; ++i) {
04501               os << space << (*i);
04502             }
04503             os << push << ")";
04504           }
04505           break;
04506         }
04507         case MINUS: {
04508           os << "(" << push << "- " << e[0] << space << e[1] << push << ")";
04509           break;
04510         }
04511         case UMINUS: {
04512           if (os.lang() == SMTLIB_LANG) {
04513             os << "(" << push << "~" << space << e[0] << push << ")";
04514           }
04515           else {
04516             os << "(" << push << "-" << space << e[0] << push << ")";
04517           }
04518           break;
04519         }
04520         case MULT:  {
04521           int i=0, iend=e.arity();
04522           if(iend == 1 && os.lang() == SMTLIB_V2_LANG) {
04523             os << e[0];
04524           } else {
04525             for(; i!=iend; ++i) {
04526               if (i < iend-1) {
04527                 os << "(" << push << "*";
04528               }
04529               os << space << e[i];
04530             }
04531             for (i=0; i < iend-1; ++i) os << push << ")";
04532           }
04533           break;
04534         }
04535         case POW:
04536           if (e[0].isRational() && e[0].getRational().isInteger()) {
04537             int i=0, iend=e[0].getRational().getInt();
04538               for(; i!=iend; ++i) {
04539                 if (i < iend-1) {
04540                   os << "(" << push << "*";
04541                 }
04542                 os << space << e[1];
04543               }
04544               for (i=0; i < iend-1; ++i) os << push << ")";
04545           }
04546           else
04547             throw SmtlibException("TheoryArithOld::print: SMTLIB: POW not supported: " + e.toString(PRESENTATION_LANG));
04548           //          os << "(" << push << "^ " << e[1] << space << e[0] << push << ")";
04549           break;
04550         case DIVIDE: {
04551           throw SmtlibException("TheoryArithOld::print: SMTLIB: unexpected use of DIVIDE");
04552           break;
04553         }
04554         case LT: {
04555           Rational r;
04556           os << "(" << push << "<" << space;
04557           os << e[0] << space << e[1] << push << ")";
04558           break;
04559         }
04560         case LE: {
04561           Rational r;
04562           os << "(" << push << "<=" << space;
04563           os << e[0] << space << e[1] << push << ")";
04564           break;
04565         }
04566         case GT: {
04567           Rational r;
04568           os << "(" << push << ">" << space;
04569           os << e[0] << space << e[1] << push << ")";
04570           break;
04571         }
04572         case GE: {
04573           Rational r;
04574           os << "(" << push << ">=" << space;
04575           os << e[0] << space << e[1] << push << ")";
04576           break;
04577         }
04578         case DARK_SHADOW:
04579           throw SmtlibException("TheoryArithOld::print: SMTLIB: DARK_SHADOW not supported");
04580     os << "(" << push << "DARK_SHADOW" << space << e[0]
04581        << space << e[1] << push << ")";
04582     break;
04583         case GRAY_SHADOW:
04584           throw SmtlibException("TheoryArithOld::print: SMTLIB: GRAY_SHADOW not supported");
04585     os << "GRAY_SHADOW(" << push << e[0] << ","  << space << e[1]
04586        << "," << space << e[2] << "," << space << e[3] << push << ")";
04587     break;
04588         default:
04589           throw SmtlibException("TheoryArithOld::print: SMTLIB: default not supported");
04590           // Print the top node in the default LISP format, continue with
04591           // pretty-printing for children.
04592           e.printAST(os);
04593 
04594           break;
04595       }
04596       break; // end of case SMTLIB_LANG
04597     }
04598     case LISP_LANG:
04599       switch(e.getKind()) {
04600         case REAL:
04601         case INT:
04602         case RATIONAL_EXPR:
04603         case NEGINF:
04604         case POSINF:
04605           e.print(os);
04606           break;
04607         case SUBRANGE:
04608           if(e.arity() != 2) e.printAST(os);
04609           else
04610             os << "(" << push << "SUBRANGE" << space << e[0]
04611          << space << e[1] << push << ")";
04612           break;
04613         case IS_INTEGER:
04614     if(e.arity() == 1)
04615       os << "(" << push << "IS_INTEGER" << space << e[0] << push << ")";
04616     else
04617       e.printAST(os);
04618     break;
04619         case PLUS:  {
04620           int i=0, iend=e.arity();
04621           os << "(" << push << "+";
04622           for(; i!=iend; ++i) os << space << e[i];
04623           os << push << ")";
04624           break;
04625         }
04626         case MINUS:
04627         //os << "(" << push << e[0] << space << "- " << e[1] << push << ")";
04628     os << "(" << push << "- " << e[0] << space << e[1] << push << ")";
04629           break;
04630         case UMINUS:
04631           os << "(" << push << "-" << space << e[0] << push << ")";
04632           break;
04633         case MULT:  {
04634           int i=0, iend=e.arity();
04635           os << "(" << push << "*";
04636           for(; i!=iend; ++i) os << space << e[i];
04637           os << push << ")";
04638           break;
04639         }
04640         case POW:
04641           os << "(" << push << "^ " << e[1] << space << e[0] << push << ")";
04642           break;
04643         case DIVIDE:
04644           os << "(" << push << "/ " << e[0] << space << e[1] << push << ")";
04645           break;
04646         case LT:
04647           os << "(" << push << "< " << e[0] << space << e[1] << push << ")";
04648           break;
04649         case LE:
04650           os << "(" << push << "<= " << e[0] << space << e[1] << push << ")";
04651           break;
04652         case GT:
04653           os << "(" << push << "> " << e[1]  << space << e[0] << push << ")";
04654           break;
04655         case GE:
04656           os << "(" << push << ">= " << e[0] << space << e[1] << push << ")";
04657           break;
04658         case DARK_SHADOW:
04659     os << "(" << push << "DARK_SHADOW" << space << e[0]
04660        << space << e[1] << push << ")";
04661     break;
04662         case GRAY_SHADOW:
04663     os << "(" << push << "GRAY_SHADOW" << space << e[0] << space
04664        << e[1] << space << e[2] << space << e[3] << push << ")";
04665     break;
04666         default:
04667           // Print the top node in the default LISP format, continue with
04668           // pretty-printing for children.
04669           e.printAST(os);
04670 
04671           break;
04672       }
04673       break; // end of case LISP_LANG
04674     default:
04675      // Print the top node in the default LISP format, continue with
04676      // pretty-printing for children.
04677        e.printAST(os);
04678   }
04679   return os;
04680 }
04681 
04682 Theorem TheoryArithOld::inequalityToFind(const Theorem& inequalityThm, bool normalizeRHS) {
04683 
04684   // Which side of the inequality
04685   int index = (normalizeRHS ? 1 : 0);
04686 
04687   TRACE("arith find", "inequalityToFind(", int2string(index) + ", " + inequalityThm.getExpr().toString(), ")");
04688 
04689   // Get the inequality expression
04690   const Expr& inequality = inequalityThm.getExpr();
04691 
04692   // The theorem we will return
04693   Theorem inequalityFindThm;
04694 
04695   // If the inequality side has a find
04696   if (inequality[index].hasFind()) {
04697     // Get the find of the rhs (lhs)
04698     Theorem rhsFindThm = inequality[index].getFind();
04699     // Get the theorem simplifys the find (in case the updates haven't updated all the finds yet
04700       // Fixed with d_theroyCore.inUpdate()
04701         rhsFindThm = transitivityRule(rhsFindThm, simplify(rhsFindThm.getRHS()));
04702       // If not the same as the original
04703       Expr rhsFind = rhsFindThm.getRHS();
04704       if (rhsFind != inequality[index]) {
04705         // Substitute in the inequality
04706         vector<unsigned> changed;
04707         vector<Theorem> children;
04708         changed.push_back(index);
04709         children.push_back(rhsFindThm);
04710         rhsFindThm = iffMP(inequalityThm, substitutivityRule(inequality, changed, children));
04711         // If on the left-hand side, we are done
04712         if (index == 0)
04713           inequalityFindThm = rhsFindThm;
04714         else
04715           // If on the right-hand side and left-hand side is 0, normalize it
04716           if (inequality[0].isRational() && inequality[0].getRational() == 0)
04717             inequalityFindThm = normalize(rhsFindThm);
04718           else
04719             inequalityFindThm = rhsFindThm;
04720       } else
04721         inequalityFindThm = inequalityThm;
04722   } else
04723       inequalityFindThm = inequalityThm;
04724 
04725 
04726   TRACE("arith find", "inequalityToFind ==>", inequalityFindThm.getExpr(), "");
04727 
04728   return inequalityFindThm;
04729 }
04730 
04731 void TheoryArithOld::registerAtom(const Expr& e) {
04732   // Trace it
04733   TRACE("arith atoms", "registerAtom(", e.toString(), ")");
04734 
04735   // Mark it
04736   formulaAtoms[e] = true;
04737 
04738   // If it is a atomic formula, add it to the map
04739   if (e.isAbsAtomicFormula() && isIneq(e)) {
04740     Expr rightSide    = e[1];
04741     Rational leftSide = e[0].getRational();
04742 
04743     //Get the terms for : c1 op t1 and t2 -op c2
04744     Expr t1, t2;
04745     Rational c1, c2;
04746     extractTermsFromInequality(e, c1, t1, c2, t2);
04747 
04748     if (true) {
04749       TRACE("arith atoms", "registering lower bound for ", t1.toString(), " = " + c1.toString() + ")");
04750       formulaAtomLowerBound[t1].insert(pair<Rational, Expr>(c1, e));
04751 
04752       // See if the bounds on the registered term can infered from already asserted facts
04753       CDMap<Expr, Rational>::iterator lowerBoundFind = termLowerBound.find(t1);
04754       if (lowerBoundFind != termLowerBound.end()) {
04755         Rational boundValue = (*lowerBoundFind).second;
04756         Theorem boundThm = termLowerBoundThm[t1];
04757         Expr boundIneq = boundThm.getExpr();
04758         if (boundValue > c1 || (boundValue == c1 && !(boundIneq.getKind() == LE && e.getKind() == LT))) {
04759           enqueueFact(getCommonRules()->implMP(boundThm, d_rules->implyWeakerInequality(boundIneq, e)));
04760         }
04761       }
04762 
04763       // See if the bounds on the registered term can falsified from already asserted facts
04764       CDMap<Expr, Rational>::iterator upperBoundFind = termUpperBound.find(t1);
04765       if (upperBoundFind != termUpperBound.end()) {
04766         Rational boundValue = (*upperBoundFind).second;
04767         Theorem boundThm = termUpperBoundThm[t1];
04768         Expr boundIneq = boundThm.getExpr();
04769         if (boundValue < c1 || (boundValue == c1 && boundIneq.getKind() == LT && e.getKind() == LT)) {
04770           enqueueFact(getCommonRules()->implMP(boundThm, d_rules->implyNegatedInequality(boundIneq, e)));
04771         }
04772       }
04773 
04774       TRACE("arith atoms", "registering upper bound for ", t2.toString(), " = " + c2.toString() + ")");
04775       formulaAtomUpperBound[t2].insert(pair<Rational, Expr>(c2, e));
04776     }
04777   }
04778 }
04779 
04780 TheoryArithOld::DifferenceLogicGraph::DifferenceLogicGraph(TheoryArithOld* arith, TheoryCore* core, ArithProofRules* rules, Context* context)
04781   : d_pathLenghtThres(&(core->getFlags()["pathlength-threshold"].getInt())),
04782     arith(arith),
04783     core(core),
04784     rules(rules),
04785     unsat_theorem(context),
04786     biggestEpsilon(context, 0, 0),
04787     smallestPathDifference(context, 1, 0),
04788     leGraph(context),
04789     varInCycle(context)
04790 {
04791 }
04792 
04793 Theorem TheoryArithOld::DifferenceLogicGraph::getUnsatTheorem() {
04794   return unsat_theorem;
04795 }
04796 
04797 bool TheoryArithOld::DifferenceLogicGraph::isUnsat() {
04798   return !getUnsatTheorem().isNull();
04799 }
04800 
04801 bool TheoryArithOld::DifferenceLogicGraph::existsEdge(const Expr& x, const Expr& y) {
04802   Expr index = x - y;
04803 
04804   Graph::iterator find_le = leGraph.find(index);
04805   if (find_le != leGraph.end()) {
04806     EdgeInfo edge_info = (*find_le).second;
04807     if (edge_info.isDefined()) return true;
04808   }
04809 
04810   return false;
04811 }
04812 
04813 bool TheoryArithOld::DifferenceLogicGraph::inCycle(const Expr& x) {
04814   return (varInCycle.find(x) != varInCycle.end());
04815 }
04816 
04817 TheoryArithOld::DifferenceLogicGraph::Graph::ElementReference TheoryArithOld::DifferenceLogicGraph::getEdge(const Expr& x, const Expr& y) {
04818   Expr index = x - y;
04819   Graph::ElementReference edge_info = leGraph[index];
04820 
04821   // If a new edge and x != y, then add vertices to the apropriate lists
04822   if (x != y && !edge_info.get().isDefined()) {
04823 
04824     // Adding a new edge, take a resource
04825     core->getResource();
04826 
04827     EdgesList::iterator y_it = incomingEdges.find(y);
04828     if (y_it == incomingEdges.end() || (*y_it).second == 0) {
04829       CDList<Expr>* list = new(true) CDList<Expr>(core->getCM()->getCurrentContext());
04830       list->push_back(x);
04831       incomingEdges[y] = list;
04832     } else
04833       ((*y_it).second)->push_back(x);
04834 
04835     EdgesList::iterator x_it = outgoingEdges.find(x);
04836     if (x_it == outgoingEdges.end() || (*x_it).second == 0) {
04837       CDList<Expr>* list = new(true) CDList<Expr>(core->getCM()->getCurrentContext());
04838       list->push_back(y);
04839       outgoingEdges[x] = list;
04840     } else
04841       ((*x_it).second)->push_back(y);
04842   }
04843 
04844   return edge_info;
04845 }
04846 
04847 TheoryArithOld::DifferenceLogicGraph::EpsRational TheoryArithOld::DifferenceLogicGraph::getEdgeWeight(const Expr& x, const Expr& y) {
04848   if (!existsEdge(x, y))
04849     return EpsRational::PlusInfinity;
04850   else {
04851     EdgeInfo edgeInfo = getEdge(x, y).get();
04852     return edgeInfo.length;
04853   }
04854 }
04855 
04856 
04857 void TheoryArithOld::DifferenceLogicGraph::addEdge(const Expr& x, const Expr& y, const Rational& bound, const Theorem& edge_thm) {
04858 
04859   TRACE("arith diff", x, " --> ", y);
04860   DebugAssert(x != y, "addEdge, given two equal expressions!");
04861 
04862   if (isUnsat()) return;
04863 
04864     // If out of resources, bail out
04865   if (core->outOfResources()) return;
04866 
04867   // Get the kind of the inequality (NOTE isNull -- for model computation we add a vertex with no theorem)
04868   // FIXME: Later, add a debug assert for the theorem that checks that this variable is cvc3diffLogicSource
04869   int kind = (edge_thm.isNull() ? LE : edge_thm.getExpr().getKind());
04870   DebugAssert(kind == LT || kind == LE, "addEdge, not an <= or <!");
04871 
04872   // Get the EpsRational bound
04873   Rational k = (kind == LE ? 0 : -1);
04874   EpsRational c(bound, k);
04875 
04876   // Get the current (or a fresh new edge info)
04877   Graph::ElementReference edgeInfoRef = getEdge(x, y);
04878   // If uninitialized, or smaller length (we prefer shorter paths, so one edge is better)
04879   EdgeInfo edgeInfo = edgeInfoRef.get();
04880   // If the edge changed to the better, do the work
04881   if (!edgeInfo.isDefined() || c <= edgeInfo.length) {
04882 
04883     // Update model generation data
04884     if (edgeInfo.isDefined()) {
04885       EpsRational difference = edgeInfo.length - c;
04886       Rational rationalDifference = difference.getRational();
04887       if (rationalDifference > 0 && rationalDifference < smallestPathDifference) {
04888         smallestPathDifference = rationalDifference;
04889         TRACE("diff model", "smallest path difference : ", smallestPathDifference, "");
04890       }
04891     }
04892     Rational newEpsilon = - c.getEpsilon();
04893     if (newEpsilon > biggestEpsilon) {
04894       biggestEpsilon = newEpsilon;
04895       TRACE("diff model", "biggest epsilon : ", biggestEpsilon, "");
04896     }
04897 
04898     // Set the edge info
04899     edgeInfo.length = c;
04900     edgeInfo.explanation = edge_thm;
04901     edgeInfo.path_length_in_edges = 1;
04902     edgeInfoRef = edgeInfo;
04903 
04904 
04905     // Try simple cycle x --> y --> x, to keep invariants (no cycles or one negative)
04906     if (existsEdge(y, x)) {
04907       varInCycle[x] = true;
04908       varInCycle[y] = true;
04909       tryUpdate(x, y, x);
04910       if (isUnsat())
04911         return;
04912     }
04913 
04914       // For all edges coming into x, z ---> x,  update z ---> y and add updated ones to the updated_in_y vector
04915     CDList<Expr>* in_x = incomingEdges[x];
04916     vector<Expr> updated_in_y;
04917     updated_in_y.push_back(x);
04918 
04919     // If there
04920     if (in_x) {
04921       IF_DEBUG(int total = 0; int updated = 0;);
04922       for (unsigned it = 0; it < in_x->size() && !isUnsat(); it ++) {
04923         const Expr& z = (*in_x)[it];
04924         if (z != arith->zero && z.hasFind() && core->find(z).getRHS() != z) continue;
04925         if (z != y && z != x && x != y) {
04926           IF_DEBUG(total ++;);
04927           TRACE("diff update", "trying with ", z.toString() + " --> ", x.toString());
04928           if (tryUpdate(z, x, y)) {
04929             updated_in_y.push_back(z);
04930             IF_DEBUG(updated++;);
04931           }
04932         }
04933       }
04934       TRACE("diff updates", "Updates : ", int2string(updated), " of " + int2string(total));
04935     }
04936 
04937     // For all edges coming into y, z_1 ---> y, and all edges going out of y, y ---> z_2, update z1 --> z_2
04938     CDList<Expr>* out_y = outgoingEdges[y];
04939     if (out_y)
04940       for (unsigned it_z1 = 0; it_z1 < updated_in_y.size() && !isUnsat(); it_z1 ++) {
04941         for (unsigned it_z2 = 0; it_z2 < out_y->size() && !isUnsat(); it_z2 ++) {
04942           const Expr& z1 = updated_in_y[it_z1];
04943           const Expr& z2 = (*out_y)[it_z2];
04944           if (z2 != arith->zero && z2.hasFind() && core->find(z2).getRHS() != z2) continue;
04945           if (z1 != z2 && z1 != y && z2 != y)
04946             tryUpdate(z1, y, z2);
04947         }
04948       }
04949 
04950   } else {
04951     TRACE("arith propagate", "could have propagated ", edge_thm.getExpr(), edge_thm.isAssump() ? " ASSUMPTION " : "not assumption");
04952 
04953   }
04954 
04955 }
04956 
04957 void TheoryArithOld::DifferenceLogicGraph::getEdgeTheorems(const Expr& x, const Expr& z, const EdgeInfo& edgeInfo, std::vector<Theorem>& outputTheorems) {
04958   TRACE("arith diff", "Getting theorems from ", x, " to " + z.toString() + " length = " + edgeInfo.length.toString() + ", edge_length = " + int2string(edgeInfo.path_length_in_edges));
04959 
04960   if (edgeInfo.path_length_in_edges == 1) {
04961     DebugAssert(x == sourceVertex || z == sourceVertex || !edgeInfo.explanation.isNull(), "Edge from " + x.toString() + " to " + z.toString() + " has no theorem!");
04962     if (x != sourceVertex && z != sourceVertex)
04963       outputTheorems.push_back(edgeInfo.explanation);
04964   }
04965   else {
04966     const Expr& y = edgeInfo.in_path_vertex;
04967     EdgeInfo x_y = getEdge(x, y);
04968     DebugAssert(x_y.isDefined(), "getEdgeTheorems: the cycle edge is not defined!");
04969     EdgeInfo y_z = getEdge(y, z);
04970     DebugAssert(y_z.isDefined(), "getEdgeTheorems: the cycle edge is not defined!");
04971     getEdgeTheorems(x, y, x_y, outputTheorems);
04972     getEdgeTheorems(y, z, y_z, outputTheorems);
04973   }
04974 }
04975 
04976 void TheoryArithOld::DifferenceLogicGraph::analyseConflict(const Expr& x, int kind) {
04977 
04978   // Get the cycle info
04979   Graph::ElementReference x_x_cycle_ref = getEdge(x, x);
04980   EdgeInfo x_x_cycle = x_x_cycle_ref.get();
04981 
04982   DebugAssert(x_x_cycle.isDefined(), "analyseConflict: the cycle edge is not defined!");
04983 
04984   // Vector to keep the theorems in
04985   vector<Theorem> inequalities;
04986 
04987   // Get the theorems::analyse
04988   getEdgeTheorems(x, x, x_x_cycle, inequalities);
04989 
04990   // Set the unsat theorem
04991   unsat_theorem = rules->cycleConflict(inequalities);
04992 
04993   TRACE("diff unsat", "negative cycle : ", int2string(inequalities.size()), " vertices.");
04994 }
04995 
04996 bool TheoryArithOld::DifferenceLogicGraph::tryUpdate(const Expr& x, const Expr& y, const Expr& z) {
04997 
04998   // x -> y -> z, if z -> x they are all in a cycle
04999   if (existsEdge(z, x)) {
05000     varInCycle[x] = true;
05001     varInCycle[y] = true;
05002     varInCycle[z] = true;
05003   }
05004 
05005   //Get all the edges
05006   Graph::ElementReference x_y_le_ref = getEdge(x, y);
05007   EdgeInfo x_y_le = x_y_le_ref;
05008   if (*d_pathLenghtThres >= 0 && x_y_le.path_length_in_edges > *d_pathLenghtThres) return false;
05009 
05010   Graph::ElementReference y_z_le_ref = getEdge(y, z);
05011   EdgeInfo y_z_le = y_z_le_ref;
05012   if (*d_pathLenghtThres >= 0 && y_z_le.path_length_in_edges > *d_pathLenghtThres) return false;
05013 
05014   Graph::ElementReference x_z_le_ref = getEdge(x, z);
05015   EdgeInfo x_z_le = x_z_le_ref;
05016 
05017   bool cycle = (x == z);
05018   bool updated = false;
05019 
05020   // Try <= + <= --> <=
05021   if (!isUnsat() && x_y_le.isDefined() && y_z_le.isDefined()) {
05022     EpsRational combined_length = x_y_le.length + y_z_le.length;
05023     int combined_edge_length = x_y_le.path_length_in_edges + y_z_le.path_length_in_edges;
05024 
05025     if (!x_z_le.isDefined() || combined_length < x_z_le.length ||
05026         (combined_length == x_z_le.length && (combined_edge_length < x_z_le.path_length_in_edges))) {
05027 
05028       if (!cycle || combined_length <= EpsRational::Zero) {
05029 
05030         if (!cycle || combined_length < EpsRational::Zero) {
05031 
05032           // Remember the path differences
05033           if (!cycle) {
05034             EpsRational difference = x_z_le.length - combined_length;
05035             Rational rationalDifference = difference.getRational();
05036             Rational newEpsilon = - x_z_le.length.getEpsilon();
05037             if (rationalDifference > 0 && rationalDifference < smallestPathDifference) {
05038               smallestPathDifference = rationalDifference;
05039               TRACE("diff model", "smallest path difference : ", smallestPathDifference, "");
05040             }
05041             if (newEpsilon > biggestEpsilon) {
05042               biggestEpsilon = newEpsilon;
05043               TRACE("diff model", "biggest epsilon : ", biggestEpsilon, "");
05044             }
05045           }
05046 
05047           // If we have a constraint among two integers variables strenghten it
05048           bool addAndEnqueue = false;
05049           if (core->okToEnqueue() && !combined_length.isInteger())
05050             if (x.getType() == arith->intType() && z.getType() == arith->intType())
05051               addAndEnqueue = true;
05052 
05053           x_z_le.length = combined_length;
05054           x_z_le.path_length_in_edges = combined_edge_length;
05055           x_z_le.in_path_vertex = y;
05056           x_z_le_ref = x_z_le;
05057 
05058           if (addAndEnqueue) {
05059             vector<Theorem> pathTheorems;
05060             getEdgeTheorems(x, z, x_z_le, pathTheorems);
05061             core->enqueueFact(rules->addInequalities(pathTheorems));
05062           }
05063 
05064           TRACE("arith diff", x.toString() + " -- > " + z.toString(), " : ", combined_length.toString());
05065           updated = true;
05066         } else
05067           if (core->okToEnqueue()) {
05068             // 0 length cycle
05069             vector<Theorem> antecedentThms;
05070             getEdgeTheorems(x, y, x_y_le, antecedentThms);
05071             getEdgeTheorems(y, z, y_z_le, antecedentThms);
05072             core->enqueueFact(rules->implyEqualities(antecedentThms));
05073           }
05074 
05075         // Try to propagate somthing in the original formula
05076         if (updated && !cycle && x != sourceVertex && z != sourceVertex && core->okToEnqueue())
05077           arith->tryPropagate(x, z, x_z_le, LE);
05078 
05079       }
05080 
05081       if (cycle && combined_length < EpsRational::Zero)
05082         analyseConflict(x, LE);
05083     }
05084   }
05085 
05086   return updated;
05087 }
05088 
05089 void TheoryArithOld::DifferenceLogicGraph::expandSharedTerm(const Expr& x) {
05090 
05091 }
05092 
05093 TheoryArithOld::DifferenceLogicGraph::~DifferenceLogicGraph() {
05094   for (EdgesList::iterator it = incomingEdges.begin(), it_end = incomingEdges.end(); it != it_end; it ++) {
05095     if ((*it).second) {
05096       delete (*it).second;
05097       free ((*it).second);
05098     }
05099   }
05100   for (EdgesList::iterator it = outgoingEdges.begin(), it_end = outgoingEdges.end(); it != it_end; it ++) {
05101     if ((*it).second) {
05102       delete (*it).second;
05103       free ((*it).second);
05104     }
05105   }
05106 }
05107 
05108 void TheoryArithOld::tryPropagate(const Expr& x, const Expr& y, const DifferenceLogicGraph::EdgeInfo& x_y_edge, int kind) {
05109 
05110   TRACE("diff atoms", "trying propagation", " x = " + x.toString(), " y = " + y.toString());
05111 
05112   // bail on non representative terms (we don't pass non-representative terms)
05113 //  if (x.hasFind() && find(x).getRHS() != x) return;
05114 //  if (y.hasFind() && find(y).getRHS() != y) return;
05115 
05116   // given edge x - z (kind) lenth
05117 
05118   // Make the index (c1 <= y - x)
05119   vector<Expr> t1_summands;
05120   t1_summands.push_back(rat(0));
05121   if (y != zero) t1_summands.push_back(y);
05122   // We have to canonize in case it is nonlinear
05123   // nonlinear terms are canonized with a constants --> 1*x*y, hence (-1)*1*x*y will not be canonical
05124   if (x != zero) t1_summands.push_back(canon(rat(-1)*x).getRHS());
05125   Expr t1 = canon(plusExpr(t1_summands)).getRHS();
05126 
05127   TRACE("diff atoms", "trying propagation", " t1 = " + t1.toString(), "");
05128 
05129   // The constant c1 <= y - x
05130   Rational c1 = - x_y_edge.length.getRational();
05131 
05132   // See if we can propagate anything to the formula atoms
05133   // c1 <= t1 ===> c <= t1 for c < c1
05134   AtomsMap::iterator find     = formulaAtomLowerBound.find(t1);
05135   AtomsMap::iterator find_end = formulaAtomLowerBound.end();
05136   if (find != find_end) {
05137         set< pair<Rational, Expr> >::iterator bounds     = (*find).second.begin();
05138         set< pair<Rational, Expr> >::iterator bounds_end = (*find).second.end();
05139         while (bounds != bounds_end) {
05140           const Expr& implied = (*bounds).second;
05141           // Try to do some theory propagation
05142           if ((*bounds).first < c1 || (implied.getKind() == LE && (*bounds).first == c1)) {
05143             TRACE("diff atoms", "found propagation", "", "");
05144                       // c1 <= t1 => c <= t1 (for c <= c1)
05145             // c1 < t1  => c <= t1 (for c <= c1)
05146             // c1 <= t1 => c < t1  (for c < c1)
05147             vector<Theorem> antecedentThms;
05148             diffLogicGraph.getEdgeTheorems(x, y, x_y_edge, antecedentThms);
05149             Theorem impliedThm = d_rules->implyWeakerInequalityDiffLogic(antecedentThms, implied);
05150             enqueueFact(impliedThm);
05151           }
05152           bounds ++;
05153         }
05154   }
05155 
05156   //
05157   // c1 <= t1 ==> !(t1 <= c) for c < c1
05158   //          ==> !(-c <= t2)
05159   // i.e. all coefficient in in the implied are opposite of t1
05160   find     = formulaAtomUpperBound.find(t1);
05161   find_end = formulaAtomUpperBound.end();
05162   if (find != find_end) {
05163     set< pair<Rational, Expr> >::iterator bounds     = (*find).second.begin();
05164         set< pair<Rational, Expr> >::iterator bounds_end = (*find).second.end();
05165         while (bounds != bounds_end) {
05166           const Expr& implied = (*bounds).second;
05167           // Try to do some theory propagation
05168           if ((*bounds).first < c1) {
05169             TRACE("diff atoms", "found negated propagation", "", "");
05170             vector<Theorem> antecedentThms;
05171           diffLogicGraph.getEdgeTheorems(x, y, x_y_edge, antecedentThms);
05172           Theorem impliedThm = d_rules->implyNegatedInequalityDiffLogic(antecedentThms, implied);
05173           enqueueFact(impliedThm);
05174           }
05175           bounds ++;
05176         }
05177   }
05178 }
05179 
05180 void TheoryArithOld::DifferenceLogicGraph::computeModel() {
05181 
05182   // If source vertex is null, create it
05183   if (sourceVertex.isNull()) {
05184     Theorem thm_exists_zero = arith->getCommonRules()->varIntroSkolem(arith->zero);
05185     sourceVertex = thm_exists_zero.getExpr()[1];
05186   }
05187 
05188   // The empty theorem to pass around
05189   Theorem thm;
05190 
05191   // Add an edge to all the vertices
05192   EdgesList::iterator vertexIt    = incomingEdges.begin();
05193   EdgesList::iterator vertexItEnd = incomingEdges.end();
05194   for (; vertexIt != vertexItEnd; vertexIt ++) {
05195     Expr vertex = (*vertexIt).first;
05196     if (core->find(vertex).getRHS() != vertex) continue;
05197     if (vertex != sourceVertex && !existsEdge(sourceVertex, vertex))
05198       addEdge(sourceVertex, vertex, 0, thm);
05199   }
05200   vertexIt    = outgoingEdges.begin();
05201   vertexItEnd = outgoingEdges.end();
05202   for (; vertexIt != vertexItEnd; vertexIt ++) {
05203     Expr vertex = (*vertexIt).first;
05204     if (core->find(vertex).getRHS() != vertex) continue;
05205     if (vertex != sourceVertex && !existsEdge(sourceVertex, vertex))
05206       addEdge(sourceVertex, vertex, 0, thm);
05207   }
05208 
05209   // Also add an edge to cvcZero
05210   if (!existsEdge(sourceVertex, arith->zero))
05211     addEdge(sourceVertex, arith->zero, 0, thm);
05212 
05213   // For the < edges we will have a small enough epsilon to add
05214   // So, we will upper-bound the number of vertices and then divide
05215   // the smallest edge with that number so as to not be able to bypass
05216 
05217 }
05218 
05219 Rational TheoryArithOld::DifferenceLogicGraph::getValuation(const Expr& x) {
05220 
05221   // For numbers, return it's value
05222   if (x.isRational()) return x.getRational();
05223 
05224   // For the source vertex, we don't care
05225   if (x == sourceVertex) return 0;
05226 
05227   // The path from source to targer vertex
05228   Graph::ElementReference x_le_c_ref = getEdge(sourceVertex, x);
05229   EdgeInfo x_le_c = x_le_c_ref;
05230 
05231   // The path from source to zero (adjusment)
05232   Graph::ElementReference zero_le_c_ref = getEdge(sourceVertex, arith->zero);
05233   EdgeInfo zero_le_c = zero_le_c_ref;
05234 
05235   TRACE("diff model", "zero adjustment: ", zero_le_c.length.getRational(), "");
05236   TRACE("diff model", "zero adjustment (eps): ", zero_le_c.length.getEpsilon(), "");
05237 
05238   // Value adjusted with the epsilon
05239   Rational epsAdjustment = (biggestEpsilon > 0 ? (x_le_c.length.getEpsilon() - zero_le_c.length.getEpsilon()) * smallestPathDifference / (2 * (biggestEpsilon + 1)) : 0);
05240   Rational value = x_le_c.length.getRational() + epsAdjustment;
05241 
05242   TRACE("diff model" , "biggest epsilon: ", biggestEpsilon, "");
05243   TRACE("diff model" , "smallestPathDifference: ", smallestPathDifference, "");
05244   TRACE("diff model" , "x_le_c.getEpsilon: ", x_le_c.length.getEpsilon(), "");
05245   TRACE("diff model" , "x_le_c.length: ", x_le_c.length.getRational(), "");
05246 
05247   // Value adjusted with the shift for zero
05248   value = zero_le_c.length.getRational() - value;
05249 
05250   TRACE("diff model", "Value of ", x, " : " + value.toString());
05251 
05252   // Return it
05253   return value;
05254 }
05255 
05256 // The infinity constant
05257 const TheoryArithOld::DifferenceLogicGraph::EpsRational TheoryArithOld::DifferenceLogicGraph::EpsRational::PlusInfinity(PLUS_INFINITY);
05258 // The negative infinity constant
05259 const TheoryArithOld::DifferenceLogicGraph::EpsRational TheoryArithOld::DifferenceLogicGraph::EpsRational::MinusInfinity(MINUS_INFINITY);
05260 // The negative infinity constant
05261 const TheoryArithOld::DifferenceLogicGraph::EpsRational TheoryArithOld::DifferenceLogicGraph::EpsRational::Zero;
05262 
05263 void TheoryArithOld::addMultiplicativeSignSplit(const Theorem& case_split_thm) {
05264   multiplicativeSignSplits.push_back(case_split_thm);
05265 }
05266 
05267 bool TheoryArithOld::addPairToArithOrder(const Expr& smaller, const Expr& bigger) {
05268   TRACE("arith var order", "addPairToArithOrder(" + smaller.toString(), ", ", bigger.toString() + ")");
05269   // We only accept arithmetic terms
05270   if (!isReal(smaller.getType()) && !isInt(smaller.getType())) return false;
05271   if (!isReal(bigger.getType()) && !isInt(bigger.getType())) return false;
05272   // We don't want to introduce loops
05273   FatalAssert(!d_graph.lessThan(smaller, bigger), "The pair (" + bigger.toString() + "," + smaller.toString() + ") is already in the order");
05274   // Update the graph
05275   d_graph.addEdge(smaller, bigger);
05276   return true;
05277 }
05278 
05279 bool TheoryArithOld::isNonlinearSumTerm(const Expr& term) {
05280   if (isPow(term)) return true;
05281   if (!isMult(term)) return false;
05282   int vars = 0;
05283   for (int j = 0; j < term.arity(); j ++)
05284     if (isPow(term[j])) return true;
05285     else if (isLeaf(term[j])) {
05286       vars ++;
05287       if (vars > 1) return true;
05288     }
05289   return false;
05290 }
05291 
05292 bool TheoryArithOld::isNonlinearEq(const Expr& e) {
05293 
05294   DebugAssert(e.isEq(), "TheoryArithOld::isNonlinear: expecting an equation" + e.toString());
05295 
05296   const Expr& lhs = e[0];
05297   const Expr& rhs = e[1];
05298 
05299   if (isNonlinearSumTerm(lhs) || isNonlinearSumTerm(rhs)) return true;
05300 
05301   // Check the right-hand side
05302   for (int i = 0; i < lhs.arity(); i ++)
05303     if (isNonlinearSumTerm(lhs[i])) return true;
05304 
05305   // Check the left hand side
05306   for (int i = 0; i < rhs.arity(); i ++)
05307     if (isNonlinearSumTerm(rhs[i])) return true;
05308 
05309   return false;
05310 }
05311 
05312 
05313 bool TheoryArithOld::isPowersEquality(const Expr& eq, Expr& power1, Expr& power2) {
05314   // equality should be in the form 0 + x1^n - x2^n = 0
05315   DebugAssert(eq.isEq(), "TheoryArithOld::isPowersEquality, expecting an equality got " + eq.toString());
05316 
05317   if (!isPlus(eq[0])) return false;
05318   if (eq[0].arity() != 3) return false;
05319   if (!(eq[0][0].isRational()) || !(eq[0][0].getRational() == 0)) return false;
05320 
05321   // Process the first term
05322   Expr term1 = eq[0][1];
05323   Rational term1_c;
05324   if (isPow(term1)) {
05325     term1_c = 1;
05326     power1 = term1;
05327   } else
05328     if (isMult(term1) && term1.arity() == 2) {
05329       if (term1[0].isRational()) {
05330         term1_c = term1[0].getRational();
05331         if (isPow(term1[1])) {
05332           if (term1_c == 1) power1 = term1[1];
05333           else if (term1_c == -1) power2 = term1[1];
05334           else return false;
05335         } else return false;
05336       } else return false;
05337     } else return false;
05338 
05339   // Process the second term
05340   Expr term2 = eq[0][2];
05341   Rational term2_c;
05342   if (isPow(term2)) {
05343     term2_c = 1;
05344     power1 = term2;
05345   } else
05346     if (isMult(term2) && term2.arity() == 2) {
05347       if (term2[0].isRational()) {
05348         term2_c = term2[0].getRational();
05349         if (isPow(term2[1])) {
05350           if (term2_c == 1) power1 = term2[1];
05351           else if (term2_c == -1) power2 = term2[1];
05352           else return false;
05353         } else return false;
05354       } else return false;
05355     } else return false;
05356 
05357   // Check that they are of opposite signs
05358   if (term1_c == term2_c) return false;
05359 
05360   // Check that the powers are equal numbers
05361   if (!power1[0].isRational()) return false;
05362   if (!power2[0].isRational()) return false;
05363   if (power1[0].getRational() != power2[0].getRational()) return false;
05364 
05365   // Everything is fine
05366   return true;
05367 }
05368 
05369 bool TheoryArithOld::isPowerEquality(const Expr& eq, Rational& constant, Expr& power1) {
05370   DebugAssert(eq.isEq(), "TheoryArithOld::isPowerEquality, expecting an equality got " + eq.toString());
05371 
05372   if (!isPlus(eq[0])) return false;
05373   if (eq[0].arity() != 2) return false;
05374   if (!eq[0][0].isRational()) return false;
05375 
05376   constant = eq[0][0].getRational();
05377 
05378   Expr term = eq[0][1];
05379   if (isPow(term)) {
05380     power1 = term;
05381     constant = -constant;
05382   } else
05383     if (isMult(term) && term.arity() == 2) {
05384       if (term[0].isRational() && isPow(term[1])) {
05385         Rational term2_c = term[0].getRational();
05386         if (term2_c == 1) {
05387           power1 = term[1];
05388           constant = -constant;
05389         } else if (term2_c == -1) {
05390           power1 = term[1];
05391           return true;
05392         } else return false;
05393       } else return false;
05394     } else return false;
05395 
05396   // Check that the power is an integer
05397   if (!power1[0].isRational()) return false;
05398   if (!power1[0].getRational().isInteger()) return false;
05399 
05400   return true;
05401 }
05402 
05403 int TheoryArithOld::termDegree(const Expr& e) {
05404   if (isLeaf(e)) return 1;
05405   if (isPow(e)) return termDegree(e[1]) * e[0].getRational().getInt();
05406   if (isMult(e)) {
05407     int degree = 0;
05408     for (int i = 0; i < e.arity(); i ++) degree += termDegree(e[i]);
05409     return degree;
05410   }
05411   return 0;
05412 }
05413 
05414 bool TheoryArithOld::canPickEqMonomial(const Expr& right)
05415 {
05416   DebugAssert(right.arity() > 1, "TheoryArithOld::canPickEqMonomial, expecting > 1 child, got " + right.arity());
05417 
05418   Expr::iterator istart = right.begin();
05419   Expr::iterator iend   = right.end();
05420 
05421   // Skip the first one
05422   istart++;
05423   for(Expr::iterator i = istart; i != iend; ++i) {
05424 
05425     Expr leaf;
05426     Rational coeff;
05427 
05428     // Check if linear term
05429     if (isLeaf(*i)) {
05430       leaf = *i;
05431       coeff = 1;
05432     } else if (isMult(*i) && (*i).arity() == 2 && (*i)[0].isRational() && isLeaf((*i)[1])) {
05433       leaf = (*i)[1];
05434       coeff = abs((*i)[0].getRational());
05435     } else
05436       continue;
05437 
05438     // If integer, must be coeff 1/-1
05439     if (!isIntegerThm(leaf).isNull())
05440       if (coeff != 1 && coeff != -1)
05441         continue;
05442 
05443     // Check if a leaf in other ones
05444     Expr::iterator j;
05445     for (j = istart; j != iend; ++j)
05446       if (j != i && isLeafIn(leaf, *j))
05447         break;
05448     if (j == iend)
05449       return true;
05450   }
05451 
05452   return false;
05453 }
05454 
05455 bool TheoryArithOld::isBounded(const Expr& t, BoundsQueryType queryType) {
05456   TRACE("arith shared", "isBounded(", t.toString(), ")");
05457   return hasUpperBound(t, queryType) && hasLowerBound(t, queryType);
05458 }
05459 
05460 TheoryArithOld::DifferenceLogicGraph::EpsRational TheoryArithOld::getUpperBound(const Expr& t, BoundsQueryType queryType)
05461 {
05462   TRACE("arith shared", "getUpperBound(", t.toString(), ")");
05463 
05464   // If t is a constant it's bounded
05465   if (t.isRational()) {
05466     TRACE("arith shared", "getUpperBound(", t.toString(), ") ==> " + t.getRational().toString());
05467     return t.getRational();
05468   }
05469 
05470   // If buffered, just return it
05471   CDMap<Expr, DifferenceLogicGraph::EpsRational>::iterator find_t = termUpperBounded.find(t);
05472   if (find_t != termUpperBounded.end()) {
05473     TRACE("arith shared", "getUpperBound(", t.toString(), ") ==> " + (*find_t).second.toString());
05474     return (*find_t).second;
05475   } else if (queryType == QueryWithCacheAll) {
05476     // Asked for cache query, so no bound is found
05477     TRACE("arith shared", "getUpperBound(", t.toString(), ") ==> +inf");
05478     return DifferenceLogicGraph::EpsRational::PlusInfinity;
05479   }
05480 
05481   // Assume it's not bounded
05482   DifferenceLogicGraph::EpsRational upperBound = DifferenceLogicGraph::EpsRational::PlusInfinity;
05483 
05484   // We always buffer the leaves, so all that's left are the terms
05485   if (!isLeaf(t)) {
05486     if (isMult(t)) {
05487       // We only handle linear terms
05488       if (!isNonlinearSumTerm(t)) {
05489         // Separate the multiplication
05490         Expr c, v;
05491         separateMonomial(t, c, v);
05492         // Get the upper-bound for the variable
05493         if (c.getRational() > 0) upperBound = getUpperBound(v);
05494         else upperBound = getLowerBound(v);
05495         if (upperBound.isFinite()) upperBound = upperBound * c.getRational();
05496         else upperBound = DifferenceLogicGraph::EpsRational::PlusInfinity;
05497       }
05498     } else if (isPlus(t)) {
05499       // If one of them is unconstrained then the term itself is unconstrained
05500       upperBound = DifferenceLogicGraph::EpsRational::Zero;
05501       for (int i = 0; i < t.arity(); i ++) {
05502         Expr t_i = t[i];
05503         DifferenceLogicGraph::EpsRational t_i_upperBound = getUpperBound(t_i, queryType);
05504         if (t_i_upperBound.isFinite()) upperBound = upperBound + t_i_upperBound;
05505         else {
05506           upperBound = DifferenceLogicGraph::EpsRational::PlusInfinity;
05507           // Not-bounded, check for constrained
05508           if (queryType == QueryWithCacheLeavesAndConstrainedComputation) {
05509             for(; i < t.arity() && isConstrainedAbove(t[i], QueryWithCacheLeaves); i ++);
05510             if (i == t.arity()) {
05511               TRACE("arith shared", "getUpperBound(", t.toString(), ") ==> constrained");
05512               termConstrainedAbove[t] = true;
05513             }
05514             break;
05515           } else break;
05516         }
05517       }
05518     }
05519   }
05520 
05521   // Buffer it
05522   if (upperBound.isFinite()) {
05523     termUpperBounded[t] = upperBound;
05524     termConstrainedAbove[t] = true;
05525   }
05526 
05527   // Return if bounded or not
05528   TRACE("arith shared", "getUpperBound(", t.toString(), ") ==> " + upperBound.toString());
05529   return upperBound;
05530 }
05531 
05532 TheoryArithOld::DifferenceLogicGraph::EpsRational TheoryArithOld::getLowerBound(const Expr& t, BoundsQueryType queryType)
05533 {
05534   TRACE("arith shared", "getLowerBound(", t.toString(), ")");
05535 
05536   // If t is a constant it's bounded
05537   if (t.isRational()) {
05538     TRACE("arith shared", "getLowerBound(", t.toString(), ") ==> " + t.getRational().toString());
05539     return t.getRational();
05540   }
05541 
05542   // If buffered, just return it
05543   CDMap<Expr, DifferenceLogicGraph::EpsRational>::iterator t_find = termLowerBounded.find(t);
05544   if (t_find != termLowerBounded.end()) {
05545     TRACE("arith shared", "getLowerBound(", t.toString(), ") ==> " + (*t_find).second.toString());
05546     return (*t_find).second;
05547   } else if (queryType == QueryWithCacheAll) {
05548     // Asked for cache query, so no bound is found
05549     TRACE("arith shared", "getLowerBound(", t.toString(), ") ==> -inf");
05550     return DifferenceLogicGraph::EpsRational::MinusInfinity;
05551   }
05552 
05553   // Assume it's not bounded
05554   DifferenceLogicGraph::EpsRational lowerBound = DifferenceLogicGraph::EpsRational::MinusInfinity;
05555 
05556   // Leaves are always buffered
05557   if (!isLeaf(t)) {
05558     if (isMult(t)) {
05559       // We only handle linear terms
05560       if (!isNonlinearSumTerm(t)) {
05561         // Separate the multiplication
05562         Expr c, v;
05563         separateMonomial(t, c, v);
05564         // Get the upper-bound for the variable
05565         if (c.getRational() > 0) lowerBound = getLowerBound(v);
05566         else lowerBound = getUpperBound(v);
05567         if (lowerBound.isFinite()) lowerBound = lowerBound * c.getRational();
05568         else lowerBound = DifferenceLogicGraph::EpsRational::MinusInfinity;
05569       }
05570     } else if (isPlus(t)) {
05571       // If one of them is unconstrained then the term itself is unconstrained
05572       lowerBound = DifferenceLogicGraph::EpsRational::Zero;
05573       for (int i = 0; i < t.arity(); i ++) {
05574         Expr t_i = t[i];
05575         DifferenceLogicGraph::EpsRational t_i_lowerBound = getLowerBound(t_i, queryType);
05576         if (t_i_lowerBound.isFinite()) lowerBound = lowerBound + t_i_lowerBound;
05577         else {
05578           lowerBound = DifferenceLogicGraph::EpsRational::MinusInfinity;
05579           // Not-bounded, check for constrained
05580           if (queryType == QueryWithCacheLeavesAndConstrainedComputation) {
05581             for(; i < t.arity() && isConstrainedBelow(t[i], QueryWithCacheLeaves); i ++);
05582             if (i == t.arity()) {
05583               TRACE("arith shared", "getLowerBound(", t.toString(), ") ==> constrained");
05584               termConstrainedBelow[t] = true;
05585             }
05586             break;
05587           } else break;
05588         }
05589       }
05590     }
05591   }
05592 
05593   // Buffer it
05594   if (lowerBound.isFinite()) {
05595     termLowerBounded[t] = lowerBound;
05596     termConstrainedBelow[t] = true;
05597   }
05598 
05599   // Return if bounded or not
05600   TRACE("arith shared", "getLowerBound(", t.toString(), ") ==> " + lowerBound.toString());
05601   return lowerBound;
05602 }
05603 
05604 int TheoryArithOld::computeTermBounds()
05605 {
05606   int computeTermBoundsConstrainedCount = 0;
05607 
05608   vector<Expr> sorted_vars;
05609   // Get the variables in the topological order
05610   if (!diffLogicOnly) d_graph.getVerticesTopological(sorted_vars);
05611   // Or if difference logic only, just get them
05612   else {
05613     diffLogicGraph.getVariables(sorted_vars);
05614     IF_DEBUG(
05615         diffLogicGraph.writeGraph(cerr);
05616     )
05617   }
05618 
05619   // Go in the reverse topological order and try to see if the vats are constrained/bounded
05620   for (int i = sorted_vars.size() - 1; i >= 0; i --)
05621   {
05622     // Get the variable
05623     Expr v = sorted_vars[i];
05624 
05625     // If the find is not identity, skip it
05626     if (v.hasFind() && find(v).getRHS() != v) continue;
05627 
05628     TRACE("arith shared", "processing: ", v.toString(), "");
05629 
05630     // If the variable is not an integer, it's unconstrained, unless we are in model generation
05631     if (isIntegerThm(v).isNull() && !d_inModelCreation) continue;
05632 
05633     // We only do the computation if the variable is not already constrained
05634     if (!isConstrained(v, QueryWithCacheAll)) {
05635 
05636       // Recall if we already computed the constraint
05637       bool constrainedAbove = isConstrained(v, QueryWithCacheAll);
05638 
05639       // See if it's bounded from above in the difference graph
05640       DifferenceLogicGraph::EpsRational upperBound = diffLogicGraph.getEdgeWeight(v, zero);
05641       if (!constrainedAbove) constrainedAbove = upperBound.isFinite();
05642 
05643       // Try to refine the bound by checking projected inequalities
05644       if (!diffLogicOnly) {
05645         ExprMap<CDList<Ineq> *>::iterator v_left_find = d_inequalitiesLeftDB.find(v);
05646         // If not constraint from one side, it's unconstrained
05647         if (v_left_find != d_inequalitiesLeftDB.end()) {
05648           // Check right hand side for an unconstrained variable
05649           CDList<Ineq>*& left_list = (*v_left_find).second;
05650           if (left_list && left_list->size() > 0) {
05651             for (unsigned ineq_i = 0; ineq_i < left_list->size(); ineq_i ++) {
05652               // Get the inequality
05653               Ineq ineq = (*left_list)[ineq_i];
05654               // Get the right-hand side (v <= rhs)
05655               Expr rhs = ineq.ineq().getExpr()[1];
05656               // If rhs changed, skip it
05657               if (rhs.hasFind() && find(rhs).getRHS() != rhs) continue;
05658               // Compute the upper bound while
05659               DifferenceLogicGraph::EpsRational currentUpperBound = getUpperBound(rhs, (constrainedAbove ? QueryWithCacheLeaves : QueryWithCacheLeavesAndConstrainedComputation));
05660               if (currentUpperBound.isFinite() && (!upperBound.isFinite() || currentUpperBound < upperBound)) {
05661                 upperBound = currentUpperBound;
05662                 constrainedAbove = true;
05663               }
05664               // If not constrained, check if right-hand-side is constrained
05665               if (!constrainedAbove) constrainedAbove = isConstrainedAbove(rhs, QueryWithCacheAll);
05666             }
05667           }
05668         }
05669       }
05670       // Difference logic case (no projections)
05671       else if (!constrainedAbove) {
05672         // If there is no incoming edges, then the variable is not constrained
05673         if (!diffLogicGraph.hasIncoming(v)) constrainedAbove =  false;
05674         // If there is a cycle from t to t, all the variables
05675         // in the graph are constrained by each-other (we could
05676         // choose one, but it's too complicated)
05677         else if (diffLogicGraph.inCycle(v)) constrainedAbove = true;
05678         // Otherwise, since there is no bounds, and the cycles
05679         // can be shifted (since one of them can be taken as
05680         // unconstrained), we can assume that the variables is
05681         // not constrained. Conundrum here is that when in model-generation
05682         // we actually should take it as constrained so that it's
05683         // split on and we are on the safe side
05684         else constrainedAbove = d_inModelCreation;
05685       }
05686 
05687       // Cache the upper bound and upper constrained computation
05688       if (constrainedAbove) termConstrainedAbove[v] = true;
05689       if (upperBound.isFinite()) termUpperBounded[v] = upperBound;
05690 
05691       // Recall the below computation if it's there
05692       bool constrainedBelow = isConstrainedBelow(v, QueryWithCacheAll);
05693 
05694       // See if it's bounded from below in the difference graph
05695       DifferenceLogicGraph::EpsRational lowerBound = diffLogicGraph.getEdgeWeight(zero, v);
05696       if (lowerBound.isFinite()) lowerBound = -lowerBound;
05697       else lowerBound = DifferenceLogicGraph::EpsRational::MinusInfinity;
05698       if (!constrainedBelow) constrainedBelow = lowerBound.isFinite();
05699 
05700       // Try to refine the bound by checking projected inequalities
05701       if (!diffLogicOnly) {
05702         ExprMap<CDList<Ineq> *>::iterator v_right_find = d_inequalitiesRightDB.find(v);
05703         // If not constraint from one side, it's unconstrained
05704         if (v_right_find != d_inequalitiesRightDB.end()) {
05705           // Check right hand side for an unconstrained variable
05706           CDList<Ineq>*& right_list = (*v_right_find).second;
05707           if (right_list && right_list->size() > 0) {
05708             for (unsigned ineq_i = 0; ineq_i < right_list->size(); ineq_i ++) {
05709               // Get the inequality
05710               Ineq ineq = (*right_list)[ineq_i];
05711               // Get the right-hand side (lhs <= 0)
05712               Expr lhs = ineq.ineq().getExpr()[0];
05713               // If lhs has changed, skip it
05714               if (lhs.hasFind() && find(lhs).getRHS() != lhs) continue;
05715               // Compute the lower bound
05716               DifferenceLogicGraph::EpsRational currentLowerBound = getLowerBound(lhs, (constrainedBelow ? QueryWithCacheLeaves : QueryWithCacheLeavesAndConstrainedComputation));
05717               if (currentLowerBound.isFinite() && (!lowerBound.isFinite() || currentLowerBound > lowerBound)) {
05718                 lowerBound = currentLowerBound;
05719                 constrainedBelow = true;
05720               }
05721               // If not constrained, check if right-hand-side is constrained
05722               if (!constrainedBelow) constrainedBelow = isConstrainedBelow(lhs, QueryWithCacheAll);
05723             }
05724           }
05725         }
05726       }
05727       // Difference logic case (no projections)
05728       else if (!constrainedBelow) {
05729         // If there is no incoming edges, then the variable is not constrained
05730         if (!diffLogicGraph.hasOutgoing(v)) constrainedBelow = false;
05731         // If there is a cycle from t to t, all the variables
05732         // in the graph are constrained by each-other (we could
05733         // choose one, but it's too complicated)
05734         else if (diffLogicGraph.inCycle(v)) constrainedBelow = true;
05735         // Otherwise, since there is no bounds, and the cycles
05736         // can be shifted (since one of them can be taken as
05737         // unconstrained), we can assume that the variables is
05738         // not constrained. Conundrum here is that when in model-generation
05739         // we actually should take it as constrained so that it's
05740         // split on and we are on the safe side
05741         else constrainedBelow = d_inModelCreation;
05742       }
05743 
05744       // Cache the lower bound and lower constrained computation
05745       if (constrainedBelow) termConstrainedBelow[v] = true;
05746       if (lowerBound.isFinite()) termLowerBounded[v] = lowerBound;
05747 
05748       // Is this variable constrained
05749       if (constrainedAbove && constrainedBelow) computeTermBoundsConstrainedCount ++;
05750 
05751       TRACE("arith shared", (constrainedAbove && constrainedBelow ? "constrained " : "unconstrained "), "", "");
05752     } else
05753       computeTermBoundsConstrainedCount ++;
05754   }
05755 
05756   TRACE("arith shared", "number of constrained variables : ", int2string(computeTermBoundsConstrainedCount), " of " + int2string(sorted_vars.size()));
05757 
05758   return computeTermBoundsConstrainedCount;
05759 }
05760 
05761 bool TheoryArithOld::isConstrainedAbove(const Expr& t, BoundsQueryType queryType)
05762 {
05763   TRACE("arith shared", "isConstrainedAbove(", t.toString(), ")");
05764 
05765   // Rational numbers are constrained
05766   if (t.isRational()) {
05767     TRACE("arith shared", "isConstrainedAbove() ==> true", "", "");
05768     return true;
05769   }
05770 
05771   // Look it up in the cache
05772   CDMap<Expr, bool>::iterator t_find = termConstrainedAbove.find(t);
05773   if (t_find != termConstrainedAbove.end()) {
05774     TRACE("arith shared", "isConstrainedAbove() ==> true", "", "");
05775     return true;
05776   }
05777   else if (queryType == QueryWithCacheAll) {
05778     TRACE("arith shared", "isConstrainedAbove() ==> false", "", "");
05779     return false;
05780   }
05781 
05782   bool constrainedAbove = true;
05783 
05784   if (isLeaf(t)) {
05785     // Leaves are always cached
05786     constrainedAbove = false;
05787   } else {
05788     if (isMult(t)) {
05789       // Non-linear terms are constrained by default
05790       // we only deal with the linear stuff
05791       if (!isNonlinearSumTerm(t)) {
05792         // Separate the multiplication
05793         Expr c, v;
05794         separateMonomial(t, c, v);
05795         // Check if the variable is constrained
05796         if (c.getRational() > 0) constrainedAbove = isConstrainedAbove(v, queryType);
05797         else constrainedAbove = isConstrainedBelow(v, queryType);
05798       }
05799     } else if (isPlus(t)) {
05800       // If one of them is unconstrained then the term itself is unconstrained
05801       for (int i = 0; i < t.arity() && constrainedAbove; i ++)
05802         if (!isConstrainedAbove(t[i])) constrainedAbove = false;
05803     }
05804   }
05805 
05806   // Remember it
05807   if (constrainedAbove) termConstrainedAbove[t] = true;
05808 
05809   TRACE("arith shared", "isConstrainedAbove() ==> ", constrainedAbove ? "true" : "false", "");
05810 
05811   // Return in
05812   return constrainedAbove;
05813 }
05814 
05815 bool TheoryArithOld::isConstrainedBelow(const Expr& t, BoundsQueryType queryType)
05816 {
05817   TRACE("arith shared", "isConstrainedBelow(", t.toString(), ")");
05818 
05819   // Rational numbers are constrained
05820   if (t.isRational()) return true;
05821 
05822   // Look it up in the cache
05823   CDMap<Expr, bool>::iterator t_find = termConstrainedBelow.find(t);
05824   if (t_find != termConstrainedBelow.end()) {
05825     TRACE("arith shared", "isConstrainedBelow() ==> true", "", "");
05826     return true;
05827   }
05828   else if (queryType == QueryWithCacheAll) {
05829     TRACE("arith shared", "isConstrainedBelow() ==> false", "", "");
05830     return false;
05831   }
05832 
05833   bool constrainedBelow = true;
05834 
05835   if (isLeaf(t)) {
05836     // Leaves are always cached
05837     constrainedBelow = false;
05838   } else {
05839     if (isMult(t)) {
05840       // Non-linear terms are constrained by default
05841       // we only deal with the linear stuff
05842       if (!isNonlinearSumTerm(t)) {
05843         // Separate the multiplication
05844         Expr c, v;
05845         separateMonomial(t, c, v);
05846         // Check if the variable is constrained
05847         if (c.getRational() > 0) constrainedBelow = isConstrainedBelow(v, queryType);
05848         else constrainedBelow = isConstrainedAbove(v, queryType);
05849       }
05850     } else if (isPlus(t)) {
05851       // If one of them is unconstrained then the term itself is unconstrained
05852       constrainedBelow = true;
05853       for (int i = 0; i < t.arity() && constrainedBelow; i ++)
05854         if (!isConstrainedBelow(t[i]))
05855           constrainedBelow = false;
05856     }
05857   }
05858 
05859   // Cache it
05860   if (constrainedBelow) termConstrainedBelow[t] = true;
05861 
05862   TRACE("arith shared", "isConstrainedBelow() ==> ", constrainedBelow ? "true" : "false", "");
05863 
05864   // Return it
05865   return constrainedBelow;
05866 }
05867 
05868 bool TheoryArithOld::isConstrained(const Expr& t, bool intOnly, BoundsQueryType queryType)
05869 {
05870   TRACE("arith shared", "isConstrained(", t.toString(), ")");
05871   // For the reals we consider them unconstrained if not asked for full check
05872   if (intOnly && isIntegerThm(t).isNull()) return false;
05873   bool result = (isConstrainedAbove(t, queryType) && isConstrainedBelow(t, queryType));
05874   TRACE("arith shared", "isConstrained(", t.toString(), (result ? ") ==>  true " : ") ==>  false ") );
05875   return result;
05876 }
05877 
05878 bool TheoryArithOld::DifferenceLogicGraph::hasIncoming(const Expr& x)
05879 {
05880   EdgesList::iterator find_x = incomingEdges.find(x);
05881 
05882   // No edges at all meaning no incoming
05883   if (find_x == incomingEdges.end()) return false;
05884 
05885   // The pointer being null, also no incoming
05886   CDList<Expr>*& list = (*find_x).second;
05887   if (!list) return false;
05888 
05889   // If in model creation, source vertex goes to all vertices
05890   if (sourceVertex.isNull())
05891     return list->size() > 0;
05892   else
05893     return list->size() > 1;
05894 }
05895 
05896 bool TheoryArithOld::DifferenceLogicGraph::hasOutgoing(const Expr& x)
05897 {
05898   EdgesList::iterator find_x = outgoingEdges.find(x);
05899 
05900   // No edges at all meaning no incoming
05901   if (find_x == outgoingEdges.end()) return false;
05902 
05903   // The pointer being null, also no incoming
05904   CDList<Expr>*& list = (*find_x).second;
05905   if (!list) return false;
05906 
05907   // If the list is not empty we have outgoing edges
05908   return list->size() > 0;
05909 }
05910 
05911 void TheoryArithOld::DifferenceLogicGraph::getVariables(vector<Expr>& variables)
05912 {
05913   set<Expr> vars_set;
05914 
05915   EdgesList::iterator incoming_it     = incomingEdges.begin();
05916   EdgesList::iterator incoming_it_end = incomingEdges.end();
05917   while (incoming_it != incoming_it_end) {
05918     Expr var = (*incoming_it).first;
05919     if (var != sourceVertex)
05920       vars_set.insert(var);
05921     incoming_it ++;
05922   }
05923 
05924   EdgesList::iterator outgoing_it     = outgoingEdges.begin();
05925   EdgesList::iterator outgoing_it_end = outgoingEdges.end();
05926   while (outgoing_it != outgoing_it_end) {
05927     Expr var = (*outgoing_it).first;
05928     if (var != sourceVertex)
05929       vars_set.insert(var);
05930     outgoing_it ++;
05931   }
05932 
05933   set<Expr>::iterator set_it     = vars_set.begin();
05934   set<Expr>::iterator set_it_end = vars_set.end();
05935   while (set_it != set_it_end) {
05936     variables.push_back(*set_it);
05937     set_it ++;
05938   }
05939 }
05940 
05941 void TheoryArithOld::DifferenceLogicGraph::writeGraph(ostream& out) {
05942   return;
05943         out << "digraph G {" << endl;
05944 
05945   EdgesList::iterator incoming_it     = incomingEdges.begin();
05946   EdgesList::iterator incoming_it_end = incomingEdges.end();
05947   while (incoming_it != incoming_it_end) {
05948 
05949     Expr var_u = (*incoming_it).first;
05950 
05951     CDList<Expr>* edges = (*incoming_it).second;
05952     if (edges)
05953       for (unsigned edge_i = 0; edge_i < edges->size(); edge_i ++) {
05954         Expr var_v = (*edges)[edge_i];
05955         out << var_u.toString() << " -> " << var_v.toString() << endl;
05956       }
05957 
05958     incoming_it ++;
05959   }
05960 
05961   out << "}" << endl;
05962 }