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