theory_arith.cpp

Go to the documentation of this file.
00001 /*****************************************************************************/
00002 /*!
00003  * \file theory_arith.cpp
00004  * 
00005  * Author: Clark Barrett, Vijay Ganesh.
00006  * 
00007  * Created: Fri Jan 17 18:39:18 2003
00008  *
00009  * <hr>
00010  * Copyright (C) 2003 by the Board of Trustees of Leland Stanford
00011  * Junior University and by New York University. 
00012  *
00013  * License to use, copy, modify, sell and/or distribute this software
00014  * and its documentation for any purpose is hereby granted without
00015  * royalty, subject to the terms and conditions defined in the \ref
00016  * LICENSE file provided with this distribution.  In particular:
00017  *
00018  * - The above copyright notice and this permission notice must appear
00019  * in all copies of the software and related documentation.
00020  *
00021  * - THE SOFTWARE IS PROVIDED "AS-IS", WITHOUT ANY WARRANTIES,
00022  * EXPRESSED OR IMPLIED.  USE IT AT YOUR OWN RISK.
00023  * 
00024  * <hr>
00025  * 
00026  */
00027 /*****************************************************************************/
00028 
00029 
00030 #include "theory_arith.h"
00031 #include "arith_proof_rules.h"
00032 //#include "arith_expr.h"
00033 #include "vcl.h"
00034 #include "arith_exception.h"
00035 #include "typecheck_exception.h"
00036 #include "eval_exception.h"
00037 #include "parser_exception.h"
00038 #include "smtlib_exception.h"
00039 #include "theory_core.h"
00040 
00041 using namespace std;
00042 using namespace CVCL;
00043 
00044 
00045 ///////////////////////////////////////////////////////////////////////////////
00046 // TheoryArith::FreeConst Methods                                            //
00047 ///////////////////////////////////////////////////////////////////////////////
00048 
00049 namespace CVCL {
00050 
00051 ostream& operator<<(ostream& os, const TheoryArith::FreeConst& fc) {
00052   os << "FreeConst(r=" << fc.getConst() << ", " 
00053      << (fc.strict()? "strict" : "non-strict") << ")";
00054   return os;
00055 }
00056 
00057 ///////////////////////////////////////////////////////////////////////////////
00058 // TheoryArith::Ineq Methods                                                 //
00059 ///////////////////////////////////////////////////////////////////////////////
00060 
00061 ostream& operator<<(ostream& os, const TheoryArith::Ineq& ineq) {
00062   os << "Ineq(" << ineq.ineq().getExpr() << ", isolated on "
00063      << (ineq.varOnRHS()? "RHS" : "LHS") << ", const = "
00064      << ineq.getConst() << ")";
00065   return os;
00066 }
00067 } // End of namespace CVCL
00068 
00069 
00070 ///////////////////////////////////////////////////////////////////////////////
00071 // TheoryArith Private Methods                                               //
00072 ///////////////////////////////////////////////////////////////////////////////
00073 
00074 
00075 Theorem TheoryArith::isIntegerThm(const Expr& e) {
00076   // Quick check
00077   if(isReal(e.getType())) return Theorem();
00078   // Try harder
00079   return isIntegerDerive(Expr(IS_INTEGER, e), typePred(e));
00080 }
00081 
00082 
00083 Theorem TheoryArith::isIntegerDerive(const Expr& isIntE, const Theorem& thm) {
00084   const Expr& e = thm.getExpr();
00085   // We found it!
00086   if(e == isIntE) return thm;
00087 
00088   Theorem res;
00089   // If the theorem is an AND, look inside each child
00090   if(e.isAnd()) {
00091     int i, iend=e.arity();
00092     for(i=0; i<iend; ++i) {
00093       res = isIntegerDerive(isIntE, getCommonRules()->andElim(thm, i));
00094       if(!res.isNull()) return res;
00095     }
00096   }
00097   return res;
00098 }
00099 
00100 const Rational& TheoryArith::freeConstIneq(const Expr& ineq, bool varOnRHS) {
00101   DebugAssert(isIneq(ineq), "TheoryArith::freeConstIneq("+ineq.toString()+")");
00102   const Expr& e = varOnRHS? ineq[0] : ineq[1];
00103   
00104   switch(e.getKind()) {
00105   case PLUS:
00106     return e[0].getRational();
00107   case RATIONAL_EXPR:
00108     return e.getRational();
00109   default: { // MULT, DIV, or Variable
00110     static Rational zero(0);
00111     return zero;
00112   }
00113   }
00114 }
00115 
00116 
00117 const TheoryArith::FreeConst& 
00118 TheoryArith::updateSubsumptionDB(const Expr& ineq, bool varOnRHS,
00119                                  bool& subsumed) {
00120   TRACE("arith ineq", "TheoryArith::updateSubsumptionDB(", ineq, 
00121         ", var isolated on "+string(varOnRHS? "RHS" : "LHS")+")");
00122   DebugAssert(isLT(ineq) || isLE(ineq), "TheoryArith::updateSubsumptionDB("
00123               +ineq.toString()+")");
00124   // Indexing expression: same as ineq only without the free const
00125   Expr index;
00126   const Expr& t = varOnRHS? ineq[0] : ineq[1];
00127   bool strict(isLT(ineq));
00128   Rational c(0);
00129   if(isPlus(t)) {
00130     DebugAssert(t.arity() >= 2, "TheoryArith::updateSubsumptionDB("
00131                 +ineq.toString()+")");
00132     c = t[0].getRational(); // Extract the free const in ineq
00133     Expr newT;
00134     if(t.arity() == 2) {
00135       newT = t[1];
00136     } else {
00137       vector<Expr> kids;
00138       Expr::iterator i=t.begin(), iend=t.end();
00139       for(++i; i!=iend; ++i) kids.push_back(*i);
00140       DebugAssert(kids.size() > 0, "kids.size = "+int2string(kids.size())
00141                   +", ineq = "+ineq.toString());
00142       newT = plusExpr(kids);
00143     }
00144     if(varOnRHS)
00145       index = leExpr(newT, ineq[1]);
00146     else
00147       index = leExpr(ineq[0], newT);
00148   } else if(isRational(t)) {
00149     c = t.getRational();
00150     if(varOnRHS)
00151       index = leExpr(rat(0), ineq[1]);
00152     else
00153       index = leExpr(ineq[0], rat(0));
00154   } else if(isLT(ineq))
00155     index = leExpr(ineq[0], ineq[1]);
00156   else 
00157     index = ineq;
00158   // Now update the database, check for subsumption, and extract the constant
00159   CDMap<Expr, FreeConst>::iterator i=d_freeConstDB.find(index), 
00160     iend=d_freeConstDB.end();
00161   if(i == iend) {
00162     subsumed = false;
00163     // Create a new entry
00164     CDOmap<Expr,FreeConst>& obj = d_freeConstDB[index];
00165     obj = FreeConst(c,strict);
00166     TRACE("arith ineq", "freeConstDB["+index.toString()+"] := ", obj, "");
00167     return obj.get();
00168   } else {
00169     CDOmap<Expr,FreeConst>& obj = d_freeConstDB[index];
00170     const FreeConst& fc = obj.get();
00171     if(varOnRHS) {
00172       subsumed = (c < fc.getConst() ||
00173                   (c == fc.getConst() && (!strict || fc.strict())));
00174     } else {
00175       subsumed = (c > fc.getConst() ||
00176                   (c == fc.getConst() && (strict || !fc.strict())));
00177     }
00178     if(!subsumed) {
00179       obj = FreeConst(c,strict);
00180       TRACE("arith ineq", "freeConstDB["+index.toString()+"] := ", obj, "");
00181     }
00182     return obj.get();
00183   }
00184 }
00185 
00186 
00187 bool TheoryArith::kidsCanonical(const Expr& e) {
00188   if(isLeaf(e)) return true;
00189   bool res(true);
00190   for(int i=0; res && i<e.arity(); ++i) {
00191     Expr simp(canon(e[i]).getRHS());
00192     res = (e[i] == simp);
00193     IF_DEBUG(if(!res) debugger.getOS() << "\ne[" << i << "] = " << e[i]
00194              << "\nsimplified = " << simp << endl);
00195   }
00196   return res;
00197 }
00198 
00199 
00200 ///////////////////////////////////////////////////////////////////////////////
00201 //                                                                           //
00202 // Function: TheoryArith::canon                                              //
00203 // Author: Clark Barrett, Vijay Ganesh.                                      //
00204 // Created: Sat Feb  8 14:46:32 2003                                         //
00205 // Description: Compute a canonical form for expression e and return a       //
00206 //              theorem that e is equal to its canonical form.               //
00207 // Note that canonical form for arith expressions is one of the following:   //
00208 // 1. rational constant                                                      //
00209 // 2. arithmetic leaf                                                        //
00210 //    (i.e. variable or term from some other theory)                         //
00211 // 3. (MULT rat leaf)                                                        //
00212 //    where rat is a non-zero rational constant, leaf is an arithmetic leaf  //
00213 // 4. (PLUS const term_0 term_1 ... term_n)                                  //
00214 //    where each term_i is either a leaf or (MULT rat leaf)                  //
00215 //    and each leaf in term_i must be strictly greater than the leaf in      //
00216 //    term_{i+1}.                                                            //
00217 //                                                                           //
00218 ///////////////////////////////////////////////////////////////////////////////
00219 Theorem TheoryArith::canon(const Expr& e)
00220 {
00221   TRACE("arith canon","canon(",e,") {");
00222   DebugAssert(kidsCanonical(e), "TheoryArith::canon("+e.toString()+")");
00223   Theorem result;
00224   switch (e.getKind()) {
00225     case UMINUS: {
00226       Theorem thm = d_rules->uMinusToMult(e[0]);
00227       Expr e2 = thm.getRHS();
00228       result = transitivityRule(thm, canon(e2));
00229     }
00230       break;
00231     case PLUS: /* {
00232       Theorem plusThm, plusThm1;
00233       plusThm = d_rules->canonFlattenSum(e);
00234       plusThm1 = d_rules->canonComboLikeTerms(plusThm.getRHS());
00235       result = transitivityRule(plusThm,plusThm1);
00236     } 
00237              */
00238       result = d_rules->canonPlus(e);
00239       break;
00240     case MINUS: {
00241       DebugAssert(e.arity() == 2,"");
00242       Theorem minus_eq_sum = d_rules->minusToPlus(e[0], e[1]);
00243       // this produces e0 + (-1)*e1; we have to canonize it in 2 steps
00244       Expr sum(minus_eq_sum.getRHS());
00245       Theorem thm(canon(sum[1]));
00246       if(thm.getLHS() == thm.getRHS()) 
00247         result = canon(minus_eq_sum);
00248       // The sum changed; do the work
00249       else {
00250         vector<unsigned> changed;
00251         vector<Theorem> thms;
00252         changed.push_back(1);
00253         thms.push_back(thm);
00254         Theorem sum_eq_canon = canon(substitutivityRule(sum, changed, thms));
00255         result = transitivityRule(minus_eq_sum, sum_eq_canon);
00256       }
00257       break;
00258     }
00259   
00260     case MULT:
00261       result = d_rules->canonMult(e);
00262       break;
00263   /*
00264     case MULT: {
00265       Theorem thmMult, thmMult1;
00266       Expr exprMult;
00267       Expr e0 = e[0];
00268       Expr e1 = e[1];
00269       if(e0.isRational()) {
00270         if(rat(0) == e0)
00271         result = d_rules->canonMultZero(e1);
00272         else if (rat(1) == e0)
00273         result = d_rules->canonMultOne(e1);
00274         else
00275         switch(e1.getKind()) {
00276         case RATIONAL_EXPR :
00277           result = d_rules->canonMultConstConst(e0,e1);
00278           break;
00279         case MULT:
00280           DebugAssert(e1[0].isRational(),
00281                       "theory_arith::canon:\n  "
00282                       "canon:MULT:MULT child is not canonical: "
00283                       + e1[0].toString());
00284   
00285           thmMult = d_rules->canonMultConstTerm(e0,e1[0],e1[1]);
00286           result = transitivityRule(thmMult,canon(thmMult.getRHS()));
00287           break;
00288         case PLUS:{
00289           Theorem thmPlus, thmPlus1;
00290           Expr ePlus;
00291           std::vector<Theorem> thmPlusVector;
00292           thmPlus = d_rules->canonMultConstSum(e0,e1);
00293           ePlus = thmPlus.getRHS();
00294           Expr::iterator i = ePlus.begin();
00295           for(;i != ePlus.end();++i)
00296             thmPlusVector.push_back(canon(*i));
00297           thmPlus1 = substitutivityRule(PLUS, thmPlusVector);
00298           result = transitivityRule(thmPlus, thmPlus1);
00299           break;
00300         }
00301         default:
00302           result = reflexivityRule(e);
00303           break;
00304         }
00305       }
00306       else {
00307           if(e1.isRational()){
00308   
00309           // canonMultTermConst just reverses the order of the const and the
00310             // term.  Then canon is called again.
00311         Theorem t1 = d_rules->canonMultTermConst(e1,e0);
00312         result = transitivityRule(t1,canon(t1.getRHS()));
00313         }
00314         else
00315   
00316               // This is where the assertion for non-linear multiplication is
00317               // produced. 
00318             result =  d_rules->canonMultTerm1Term2(e0,e1);
00319       }
00320       break;
00321       }
00322   
00323   */
00324     case DIVIDE:{
00325   /*
00326       case DIVIDE:{
00327         if (e[1].isRational()) {
00328           if (e[1].getRational() == 0)
00329             throw ArithException("Divide by 0 error in "+e.toString());
00330           Theorem thm = d_rules->canonDivideVar(e[0], e[1]);
00331           Expr e2 = thm.getRHS();
00332           result =  transitivityRule(thm, canon(e2));
00333         }
00334         else 
00335         {
00336         // TODO: to be handled
00337         throw ArithException("Divide by a non-const not handled in "+e.toString());
00338         }
00339       break;
00340       }
00341   */
00342 
00343       // Division by 0 is OK (total extension, protected by TCCs)
00344 //       if (e[1].isRational() && e[1].getRational() == 0)
00345 //         throw ArithException("Divide by 0 error in "+e.toString());
00346       if (e[1].getKind() == PLUS)
00347         throw ArithException("Divide by a PLUS expression not handled in"+e.toString());
00348       result = d_rules->canonDivide(e);
00349       break;
00350     }
00351   case POW:
00352     if(e[1].isRational())
00353       result = d_rules->canonPowConst(e);
00354     else
00355       result = reflexivityRule(e);
00356     break;
00357   default:
00358       result = reflexivityRule(e);
00359       break;
00360     }
00361   TRACE("arith canon","canon => ",result," }");
00362   return result;
00363 }
00364 
00365 
00366 Theorem
00367 TheoryArith::canonRec(const Expr& e)
00368 {
00369   if (isLeaf(e)) return reflexivityRule(e);
00370   int ar = e.arity();
00371   if (ar > 0) {
00372     vector<Theorem> newChildrenThm;
00373     vector<unsigned> changed;
00374     for(int k = 0; k < ar; ++k) {
00375       // Recursively canonize the kids
00376       Theorem thm = canonRec(e[k]);
00377       if (thm.getLHS() != thm.getRHS()) {
00378         newChildrenThm.push_back(thm);
00379         changed.push_back(k);
00380       }
00381     }
00382     if(changed.size() > 0) {
00383       return canon(substitutivityRule(e, changed, newChildrenThm));
00384     }
00385   }
00386   return canon(e);
00387 }
00388 
00389 
00390 Theorem
00391 TheoryArith::canonSimplify(const Expr& e) {
00392   TRACE("arith", "canonSimplify(", e, ") {");
00393   DebugAssert(kidsCanonical(e),
00394               "TheoryArith::canonSimplify("+e.toString()+")");
00395   Expr tmp(e);
00396   Theorem thm = canon(e);
00397   if(thm.getRHS().hasFind())
00398     thm = transitivityRule(thm, find(thm.getRHS()));
00399   // We shouldn't rely on simplification in this function anymore
00400   DebugAssert(thm.getRHS() == simplifyExpr(thm.getRHS()),
00401               "canonSimplify("+e.toString()+")\n"
00402               +"canon(e) = "+thm.getRHS().toString()
00403               +"\nsimplify(canon(e)) = "+simplifyExpr(thm.getRHS()).toString());
00404 //   if(tmp != thm.getRHS())
00405 //     thm = transitivityRule(thm, simplifyThm(thm.getRHS()));
00406 //   while(tmp != thm.getRHS()) {
00407 //     tmp = thm.getRHS();
00408 //     thm = canon(thm);
00409 //     if(tmp != thm.getRHS())
00410 //       thm = transitivityRule(thm, simplifyThm(thm.getRHS()));
00411 //   }
00412   TRACE("arith", "canonSimplify =>", thm, " }");
00413   return thm;
00414 }
00415 
00416 /*! accepts a theorem, canonizes it, applies iffMP and substituvity to
00417  *  derive the canonized thm
00418  */
00419 Theorem
00420 TheoryArith::canonPred(const Theorem& thm) {
00421   vector<Theorem> thms;
00422   DebugAssert(thm.getExpr().arity() == 2,
00423               "TheoryArith::canonPred: bad theorem: "+thm.toString());
00424   Expr e(thm.getExpr());
00425   thms.push_back(canonSimplify(e[0]));
00426   thms.push_back(canonSimplify(e[1]));
00427   return iffMP(thm, substitutivityRule(e.getOp(), thms));
00428 }
00429 
00430 /*! accepts an equivalence theorem, canonizes it, applies iffMP and
00431  *  substituvity to derive the canonized thm
00432  */
00433 Theorem
00434 TheoryArith::canonPredEquiv(const Theorem& thm) {
00435   vector<Theorem> thms;
00436   DebugAssert(thm.getRHS().arity() == 2,
00437               "TheoryArith::canonPredEquiv: bad theorem: "+thm.toString());
00438   Expr e(thm.getRHS());
00439   thms.push_back(canonSimplify(e[0]));
00440   thms.push_back(canonSimplify(e[1]));
00441   return transitivityRule(thm, substitutivityRule(e.getOp(), thms));
00442 }
00443 
00444 /*! accepts an equivalence theorem whose RHS is a conjunction,
00445  *  canonizes it, applies iffMP and substituvity to derive the
00446  *  canonized thm
00447  */
00448 Theorem
00449 TheoryArith::canonConjunctionEquiv(const Theorem& thm) {
00450   vector<Theorem> thms;
00451   return thm;
00452 }
00453 
00454 /*! Psuedo-code for doSolve. (Input is an equation) (output is a Theorem)
00455  *  -# translate e to the form e' = 0
00456  *  -# if (e'.isRational()) then {if e' != 0 return false else true}
00457  *  -# a for loop checks if all the variables are integers. 
00458  *      - if not isolate a suitable real variable and call processRealEq().
00459  *      - if all variables are integers then isolate suitable variable 
00460  *         and call processIntEq(). 
00461  */
00462 Theorem TheoryArith::doSolve(const Theorem& thm)
00463 { 
00464   const Expr& e = thm.getExpr();
00465   TRACE("arith eq","doSolve(",e,") {");
00466   DebugAssert(thm.isRewrite(), "thm = "+thm.toString());
00467   Theorem eqnThm;
00468   vector<Theorem> thms;  
00469   // Move LHS to the RHS, if necessary
00470   if(e[0].isRational() && e[0].getRational() == 0)
00471     eqnThm = thm;
00472   else {
00473     eqnThm = iffMP(thm, d_rules->rightMinusLeft(e));
00474     eqnThm = canonPred(eqnThm);
00475   }
00476   // eqnThm is of the form 0 = e'
00477   // 'right' is of the form e'
00478   Expr right = eqnThm.getRHS();
00479   // Check for trivial equation
00480   if (right.isRational()) {
00481     Theorem result = iffMP(eqnThm, d_rules->constPredicate(eqnThm.getExpr()));
00482     TRACE("arith eq","doSolve => ",result," }");
00483     return result;
00484   }
00485 
00486   //normalize
00487   eqnThm = iffMP(eqnThm, normalize(eqnThm.getExpr()));
00488   right = eqnThm.getRHS();
00489   
00490   //eqn is of the form 0 = e' and is normalized where 'right' denotes e'
00491   //FIXME: change processRealEq to accept equations as well instead of theorems
00492   if(!isInteger(right)) {
00493     Theorem res;
00494     try {
00495       res = processRealEq(eqnThm);
00496     } catch(ArithException& e) {
00497       res = symmetryRule(eqnThm); // Flip to e' = 0
00498       TRACE("arith eq", "doSolve: failed to solve an equation: ", e, "");
00499       IF_DEBUG(debugger.counter("FAILED to solve real equalities")++);
00500       setIncomplete("Non-linear arithmetic inequalities");
00501     }
00502     IF_DEBUG(debugger.counter("solved real equalities")++);
00503     TRACE("arith eq", "doSolve [real] => ", res, " }");
00504     return res;
00505   }
00506   else {
00507     Theorem res = processIntEq(eqnThm);
00508     IF_DEBUG(debugger.counter("solved int equalities")++);
00509     TRACE("arith eq", "doSolve [int] => ", res, " }");
00510     return res;
00511   }
00512 }
00513 
00514 /*! pick a monomial for the input equation. This function is used only
00515  *  if the equation is an integer equation. Choose the monomial with
00516  *  the smallest absolute value of coefficient.
00517  */
00518 Expr
00519 TheoryArith::pickIntEqMonomial(const Expr& right)
00520 {
00521   DebugAssert(isPlus(right) && right.arity() > 2,
00522               "TheoryArith::pickIntEqMonomial right is wrong :-): " +
00523               right.toString());
00524   DebugAssert(right[0].isRational(),
00525               "TheoryArith::pickIntEqMonomial. right[0] must be const" +
00526               right.toString());
00527   DebugAssert(isInteger(right),
00528               "TheoryArith::pickIntEqMonomial: right is of type int: " +
00529               right.toString());
00530   //right is of the form "C + a1x1 + ... + anxn". min is initialized
00531   //to a1
00532   Expr::iterator i = right.begin();
00533   i++; //skip 'C'
00534   Rational min = isMult(*i) ? abs((*i)[0].getRational()) : 1;
00535   Expr pickedMon = *i;
00536   for(Expr::iterator iend = right.end(); i != iend; ++i) {
00537     Rational coeff = isMult(*i) ? abs((*i)[0].getRational()) : 1;
00538     if(min > coeff) {
00539       min = coeff;
00540       pickedMon = *i;
00541     }
00542   }
00543   return pickedMon;
00544 }
00545 
00546 /*! input is e1=e2<==>0=e' Theorem and some of the vars in e' are of
00547  * type REAL. isolate one of them and send back to framework. output
00548  * is "e1=e2 <==> var = e''" Theorem.
00549  */
00550 Theorem 
00551 TheoryArith::processRealEq(const Theorem& eqn)
00552 {
00553   Expr right = eqn.getRHS();
00554   // Find variable to isolate and store it in left.  Pick the largest
00555   // (according to the total ordering) variable.  FIXME: change from
00556   // total ordering to the ordering we devised for inequalities.
00557 
00558   // TODO: I have to pick a variable that appears as a variable in the
00559   // term but does not appear as a variable anywhere else.  The variable
00560   // must appear as a single leaf and not in a MULT expression with some
00561   // other variables and nor in a POW expression.
00562 
00563   bool found = false;
00564   
00565   Expr left;
00566   
00567   if (isPlus(right))  {
00568     for(int i = right.arity()-1; i>=0; --i) {
00569       Expr c = right[i];
00570       if(isRational(c))
00571         continue;
00572       if(!isInteger(c))  {
00573         if (isLeaf(c) || 
00574             ((isMult(c) && c.arity() == 2 && isLeaf(c[1])))) {
00575           int numoccurs = 0;
00576           Expr leaf = isLeaf(c) ? c : c[1];
00577           for (int j = 0; j < right.arity(); ++j) {
00578             if (j!= i
00579                 && isLeafIn(leaf, right[j])
00580                 // && leaf.subExprOf(right[j])
00581                 ) {
00582               numoccurs++;
00583               break;
00584             }
00585           }
00586           if (!numoccurs) {
00587             left = c;
00588             found = true;
00589             break;
00590           }
00591         }
00592       }
00593     }
00594   }
00595   else if ((isMult(right) && right.arity() == 2 && isLeaf(right[1])) ||
00596            isLeaf(right)) {
00597     left = right;
00598     found = true;
00599   }
00600   
00601   if (!found) {
00602     // TODO:
00603     // throw an arithmetic exception that this cannot be done.
00604     throw 
00605       ArithException("Can't find a leaf for solve in "+eqn.toString());
00606   }
00607 
00608   Rational r = -1;
00609   if (isMult(left))  {
00610     DebugAssert(left.arity() == 2, "only leaf should be chosen as lhs");
00611     DebugAssert(left[0].getRational() != 0, "left = "+left.toString());
00612     r = -1/left[0].getRational();
00613     left = left[1];
00614   }
00615 
00616   DebugAssert(isReal(getBaseType(left)) && !isInteger(left),
00617               "TheoryArith::ProcessRealEq: left is integer:\n left = "
00618               +left.toString());
00619   // Normalize equation so that coefficient of the monomial
00620   // corresponding to "left" in eqn[1] is -1
00621   Theorem result(iffMP(eqn,
00622                        d_rules->multEqn(eqn.getLHS(), eqn.getRHS(), rat(r))));
00623   result = canonPred(result);
00624 
00625   // Isolate left
00626   result = iffMP(result, d_rules->plusPredicate(result.getLHS(),
00627                                                 result.getRHS(), left, EQ));
00628   result = canonPred(result);
00629   TRACE("arith","processRealEq => ",result," }");
00630   return result;
00631 }
00632 
00633 /*!
00634  * \param eqn is a single equation 0 = e
00635  * \return an equivalent Theorem (x = t AND 0 = e'), or just x = t
00636  */
00637 Theorem
00638 TheoryArith::processSimpleIntEq(const Theorem& eqn)
00639 {
00640   TRACE("arith eq", "processSimpleIntEq(", eqn.getExpr(), ") {");
00641   DebugAssert(eqn.isRewrite(),
00642               "TheoryArith::processSimpleIntEq: eqn must be equality" +
00643               eqn.getExpr().toString());
00644 
00645   Expr right = eqn.getRHS();
00646 
00647   DebugAssert(eqn.getLHS().isRational() && 0 == eqn.getLHS().getRational(),
00648               "TheoryArith::processSimpleIntEq: LHS must be 0:\n" +
00649               eqn.getExpr().toString());
00650 
00651   //recall that 0 = c case is already handled in doSolve() function.
00652   if(isMult(right)) {
00653     //here we take care of special case 0=c.x
00654     Expr c,x;
00655     separateMonomial(right, c, x);
00656     Theorem isIntx(isIntegerThm(x));
00657     DebugAssert(!isIntx.isNull(), "right = "+right.toString());
00658     Theorem res(iffMP(eqn, d_rules->intVarEqnConst(eqn.getExpr(), isIntx)));
00659     TRACE("arith eq", "processSimpleIntEq[0 = a*x] => ", res, " }");
00660     return res;
00661   } else if(isPlus(right)) {
00662     if(2 == right.arity()) {
00663       //we take care of special cases like 0 = c + a.x, 0 = c + x,
00664       Expr c,x;
00665       separateMonomial(right[1], c, x);
00666       Theorem isIntx(isIntegerThm(x));
00667       DebugAssert(!isIntx.isNull(), "right = "+right.toString()
00668                   +"\n x = "+x.toString());
00669       Theorem res(iffMP(eqn, d_rules->intVarEqnConst(eqn.getExpr(), isIntx)));
00670       TRACE("arith eq", "processSimpleIntEq[0 = c + a*x] => ", res, " }");
00671       return res;
00672     }
00673     DebugAssert(right.arity() > 2,
00674                 "TheoryArith::processSimpleIntEq: RHS is not in correct form:"
00675                 +eqn.getExpr().toString());
00676     // Pick a suitable monomial. isolated can be of the form x, a.x, -a.x
00677     Expr isolated = pickIntEqMonomial(right);
00678     TRACE("arith eq", "processSimpleIntEq: isolated = ", isolated, "");
00679 
00680     // First, we compute the 'sign factor' with which to multiply the
00681     // eqn.  if the coeff of isolated is positive (i.e. 'isolated' is
00682     // of the form x or a.x where a>0 ) then r must be -1 and if coeff
00683     // of 'isolated' is negative, r=1.
00684     Rational r = isMult(isolated) ?
00685       ((isolated[0].getRational() > 0) ? -1 : 1) : -1;
00686     Theorem result;
00687     if (-1 == r) {
00688       // r=-1 and hence 'isolated' is 'x' or 'a.x' where a is
00689       // positive.  modify eqn (0=e') to the equation (0=canon(-1*e'))
00690       result = iffMP(eqn, d_rules->multEqn(eqn.getLHS(), right, rat(r)));
00691       result = canonPred(result);
00692       Expr e = result.getRHS();
00693 
00694       // Isolate the 'isolated'
00695       result = iffMP(result,
00696                      d_rules->plusPredicate(result.getLHS(),result.getRHS(),
00697                                             isolated, EQ));
00698     } else {
00699       //r is 1 and hence isolated is -a.x. Make 'isolated' positive.
00700       const Rational& minusa = isolated[0].getRational();
00701       Rational a = -1*minusa;
00702       isolated = (a == 1)? isolated[1] : rat(a) * isolated[1];
00703       
00704       // Isolate the 'isolated'
00705       result = iffMP(eqn, d_rules->plusPredicate(eqn.getLHS(), 
00706                                                  right,isolated,EQ));
00707     }
00708     // Canonize the result
00709     result = canonPred(result);
00710         
00711     //if isolated is 'x' or 1*x, then return result else continue processing.
00712     if(!isMult(isolated) || isolated[0].getRational() == 1) {   
00713       TRACE("arith eq", "processSimpleIntEq[x = rhs] => ", result, " }");
00714       return result;
00715     } else {
00716       DebugAssert(isMult(isolated) && isolated[0].getRational() >= 2,
00717                   "TheoryArith::processSimpleIntEq: isolated must be mult "
00718                   "with coeff >= 2.\n isolated = " + isolated.toString());
00719 
00720       // Compute IS_INTEGER() for lhs and rhs
00721       const Expr& lhs = result.getLHS();
00722       const Expr& rhs = result.getRHS();
00723       Expr a, x;
00724       separateMonomial(lhs, a, x);
00725       Theorem isIntLHS = isIntegerThm(x);
00726       vector<Theorem> isIntRHS;
00727       if(!isPlus(rhs)) { // rhs is a MULT
00728         Expr c, v;
00729         separateMonomial(rhs, c, v);
00730         isIntRHS.push_back(isIntegerThm(v));
00731         DebugAssert(!isIntRHS.back().isNull(), "");
00732       } else { // rhs is a PLUS
00733         DebugAssert(isPlus(rhs), "rhs = "+rhs.toString());
00734         DebugAssert(rhs.arity() >= 2, "rhs = "+rhs.toString());
00735         Expr::iterator i=rhs.begin(), iend=rhs.end();
00736         ++i; // Skip the free constant
00737         for(; i!=iend; ++i) {
00738           Expr c, v;
00739           separateMonomial(*i, c, v);
00740           isIntRHS.push_back(isIntegerThm(v));
00741           DebugAssert(!isIntRHS.back().isNull(), "");
00742         }
00743       }
00744       // Derive (EXISTS (x:INT): x = t2 AND 0 = t3)
00745       result = d_rules->eqElimIntRule(result, isIntLHS, isIntRHS);
00746       // Skolemize the quantifier
00747       result = getCommonRules()->skolemize(result);
00748       // Canonize t2 and t3 generated by this rule
00749       DebugAssert(result.getExpr().isAnd() && result.getExpr().arity() == 2,
00750                   "processSimpleIntEq: result = "+result.getExpr().toString());
00751       Theorem thm1 = canonPred(getCommonRules()->andElim(result, 0));
00752       Theorem thm2 = canonPred(getCommonRules()->andElim(result, 1));
00753       Theorem newRes = getCommonRules()->andIntro(thm1, thm2);
00754       if(newRes.getExpr() != result.getExpr()) result = newRes;
00755       
00756       TRACE("arith eq", "processSimpleIntEq => ", result, " }");
00757       return result;
00758     }
00759   } else {
00760     // eqn is 0 = x.  Flip it and return
00761     Theorem result = symmetryRule(eqn);
00762     TRACE("arith eq", "processSimpleIntEq[x = 0] => ", result, " }");
00763     return result;
00764   }
00765 }
00766 
00767 /*! input is e1=e2<==>0=e' Theorem and all of the vars in e' are of
00768  * type INT. isolate one of them and send back to framework. output
00769  * is "e1=e2 <==> var = e''" Theorem and some associated equations in
00770  * solved form.
00771  */
00772 Theorem 
00773 TheoryArith::processIntEq(const Theorem& eqn)
00774 {
00775   TRACE("arith eq", "processIntEq(", eqn.getExpr(), ") {");
00776   // Equations in the solved form.  
00777   std::vector<Theorem> solvedAndNewEqs;
00778   Theorem newEq(eqn), result;
00779   bool done(false);
00780   do {
00781     result = processSimpleIntEq(newEq);
00782     // 'result' is of the from (x1=t1)  AND 0=t'
00783     if(result.isRewrite()) {
00784       solvedAndNewEqs.push_back(result);
00785       done = true;
00786     }
00787     else if(!result.getExpr().isFalse()) {
00788       DebugAssert(result.getExpr().isAnd() && result.getExpr().arity() == 2,
00789                   "TheoryArith::processIntEq("+eqn.getExpr().toString()
00790                   +")\n result = "+result.getExpr().toString());
00791       solvedAndNewEqs.push_back(getCommonRules()->andElim(result, 0));
00792       newEq = getCommonRules()->andElim(result, 1);
00793     } else
00794       done = true;
00795   } while(!done);
00796   Theorem res;
00797   if(result.getExpr().isFalse()) res = result;
00798   else res = solvedForm(solvedAndNewEqs);
00799   TRACE("arith eq", "processIntEq => ", res.getExpr(), " }");
00800   return res;
00801 }
00802 
00803 /*!
00804  * Takes a vector of equations and for every equation x_i=t_i
00805  * substitutes t_j for x_j in t_i for all j>i.  This turns the system
00806  * of equations into a solved form.
00807  *
00808  * Assumption: variables x_j may appear in the RHS terms t_i ONLY for
00809  * i<j, but not for i>=j.
00810  */
00811 Theorem
00812 TheoryArith::solvedForm(const vector<Theorem>& solvedEqs) 
00813 {
00814   DebugAssert(solvedEqs.size() > 0, "TheoryArith::solvedForm()");
00815 
00816   // Trace code
00817   TRACE_MSG("arith eq", "TheoryArith::solvedForm:solvedEqs(\n  [");
00818   IF_DEBUG(if(debugger.trace("arith eq")) {
00819     for(vector<Theorem>::const_iterator j = solvedEqs.begin(),
00820           jend=solvedEqs.end(); j!=jend;++j)
00821       TRACE("arith eq", "", j->getExpr(), ",\n   ");
00822   });
00823   TRACE_MSG("arith eq", "  ]) {");
00824   // End of Trace code
00825   
00826   vector<Theorem>::const_reverse_iterator
00827     i = solvedEqs.rbegin(),
00828     iend = solvedEqs.rend();
00829   // Substitution map: a variable 'x' is mapped to a Theorem x=t.
00830   // This map accumulates the resulting solved form.
00831   ExprMap<Theorem> subst;
00832   for(; i!=iend; ++i) {
00833     if(i->isRewrite()) {
00834       Theorem thm = substAndCanonize(*i, subst);
00835       TRACE("arith eq", "solvedForm: subst["+i->getLHS().toString()+"] = ",
00836             thm.getExpr(), "");
00837       subst[i->getLHS()] = thm;
00838     }
00839     else {
00840       // This is the FALSE case: just return the contradiction
00841       DebugAssert(i->getExpr().isFalse(),
00842                   "TheoryArith::solvedForm: an element of solvedEqs must "
00843                   "be either EQ or FALSE: "+i->toString());
00844       return *i;
00845     }
00846   }
00847   // Now we've collected the solved form in 'subst'.  Wrap it up into
00848   // a conjunction and return.
00849   vector<Theorem> thms;
00850   for(ExprMap<Theorem>::iterator i=subst.begin(), iend=subst.end();
00851       i!=iend; ++i)
00852     thms.push_back(i->second);
00853   return getCommonRules()->andIntro(thms);
00854 }
00855 
00856 
00857 /*!
00858  * ASSUMPTION: 't' is a fully canonized arithmetic term, and every
00859  * element of subst is a fully canonized equation of the form x=e,
00860  * indexed by the LHS variable.
00861  */
00862 
00863 Theorem
00864 TheoryArith::substAndCanonize(const Expr& t, ExprMap<Theorem>& subst)
00865 {
00866   TRACE("arith eq", "substAndCanonize(", t, ") {");
00867   // Quick and dirty check: return immediately if subst is empty
00868   if(subst.empty()) {
00869     Theorem res(reflexivityRule(t));
00870     TRACE("arith eq", "substAndCanonize[subst empty] => ", res, " }");
00871     return res;
00872   }
00873   // Check if we can substitute 't' directly
00874   ExprMap<Theorem>::iterator i = subst.find(t), iend=subst.end();
00875   if(i!=iend) {
00876     TRACE("arith eq", "substAndCanonize[subst] => ", i->second, " }");
00877     return i->second;
00878   }
00879   // The base case: t is an i-leaf
00880   if(isLeaf(t)) {
00881     Theorem res(reflexivityRule(t));
00882     TRACE("arith eq", "substAndCanonize[i-leaf] => ", res, " }");
00883     return res;
00884   }
00885   // 't' is an arithmetic term; recurse into the children
00886   vector<Theorem> thms;
00887   vector<unsigned> changed;
00888   for(unsigned j=0, jend=t.arity(); j!=jend; ++j) {
00889     Theorem thm = substAndCanonize(t[j], subst);
00890     if(thm.getRHS() != t[j]) {
00891       thm = canon(thm);
00892       thms.push_back(thm);
00893       changed.push_back(j);
00894     }
00895   }
00896   // Do the actual substitution and canonize the result
00897   Theorem res;
00898   if(thms.size() > 0) {
00899     res = substitutivityRule(t, changed, thms);
00900     res = canon(res);
00901   }
00902   else
00903     res = reflexivityRule(t);
00904   TRACE("arith eq", "substAndCanonize => ", res, " }");
00905   return res;
00906 }
00907 
00908 
00909 /*!
00910  *  ASSUMPTION: 't' is a fully canonized equation of the form x = t,
00911  *  and so is every element of subst, indexed by the LHS variable.
00912  */
00913 
00914 Theorem
00915 TheoryArith::substAndCanonize(const Theorem& eq, ExprMap<Theorem>& subst)
00916 {
00917   // Quick and dirty check: return immediately if subst is empty
00918   if(subst.empty()) return eq;
00919 
00920   DebugAssert(eq.isRewrite(), "TheoryArith::substAndCanonize: t = "
00921               +eq.getExpr().toString());
00922   const Expr& t = eq.getRHS();
00923   // Do the actual substitution in the term t
00924   Theorem thm = substAndCanonize(t, subst);
00925   // Substitution had no result: return the original equation
00926   if(thm.getRHS() == t) return eq;
00927   // Otherwise substitute the result into the equation
00928   vector<Theorem> thms;
00929   vector<unsigned> changed;
00930   thms.push_back(thm);
00931   changed.push_back(1);
00932   return iffMP(eq, substitutivityRule(eq.getExpr(), changed, thms));
00933 }
00934 
00935 
00936 void TheoryArith::processBuffer()
00937 {
00938   // Process the inequalities in the buffer
00939   bool varOnRHS;
00940   for(; !inconsistent() && d_bufferIdx < d_buffer.size();
00941       d_bufferIdx = d_bufferIdx+1) {
00942     const Theorem& ineqThm = d_buffer[d_bufferIdx];
00943     // Skip this inequality if it is stale
00944     if(isStale(ineqThm.getExpr())) continue;
00945     Theorem thm1 = isolateVariable(ineqThm, varOnRHS);
00946     const Expr& ineq = thm1.getExpr();
00947     if((ineq).isFalse())
00948       setInconsistent(thm1);
00949     else if(!ineq.isTrue()) {
00950       // Check that the variable is indeed isolated correctly
00951       DebugAssert(varOnRHS? !isPlus(ineq[1]) : !isPlus(ineq[0]),
00952                   "TheoryArith::processBuffer(): bad result from "
00953                   "isolateVariable:\nineq = "+ineq.toString());
00954       // and project the inequality
00955       projectInequalities(thm1, varOnRHS);
00956     }
00957   }
00958 }
00959 
00960 
00961 void TheoryArith::updateStats(const Rational& c, const Expr& v)
00962 {
00963   TRACE("arith ineq", "updateStats("+c.toString()+", ", v, ")");
00964   if(c > 0) {
00965     if(d_countRight.count(v) > 0) d_countRight[v] = d_countRight[v] + 1;
00966     else d_countRight[v] = 1;
00967   }
00968   else
00969     if(d_countLeft.count(v) > 0) d_countLeft[v] = d_countLeft[v] + 1;
00970     else d_countLeft[v] = 1;
00971 }
00972 
00973 
00974 void TheoryArith::updateStats(const Expr& monomial)
00975 {
00976   Expr c, m;
00977   separateMonomial(monomial, c, m);
00978   updateStats(c.getRational(), m);
00979 }
00980 
00981 
00982 void TheoryArith::addToBuffer(const Theorem& thm) {
00983   // First, turn the inequality into 0 < rhs
00984   // FIXME: check if this can be optimized away
00985   Theorem result(thm);
00986   const Expr& e = thm.getExpr();
00987   // int kind = e.getKind();
00988   if(!(e[0].isRational() && e[0].getRational() == 0)) {
00989     result = iffMP(result, d_rules->rightMinusLeft(e));
00990     result = canonPred(result);
00991   }
00992   TRACE("arith ineq", "addToBuffer(", result.getExpr(), ")");
00993   // Push it into the buffer
00994   d_buffer.push_back(thm);
00995 
00996   // Collect the statistics about variables
00997   const Expr& rhs = thm.getExpr()[1];
00998   if(isPlus(rhs))
00999     for(Expr::iterator i=rhs.begin(), iend=rhs.end(); i!=iend; ++i)
01000       updateStats(*i);
01001   else // It's a monomial
01002     updateStats(rhs);
01003 }
01004 
01005 
01006 Theorem TheoryArith::isolateVariable(const Theorem& inputThm, 
01007                                      bool& isolatedVarOnRHS)
01008 {
01009   Theorem result(inputThm);
01010   const Expr& e = inputThm.getExpr();
01011   TRACE("arith","isolateVariable(",e,") {");
01012   TRACE("arith ineq", "isolateVariable(", e, ") {");
01013   //we assume all the children of e are canonized
01014   DebugAssert(isLT(e)||isLE(e),
01015               "TheoryArith::isolateVariable: " + e.toString() +
01016               " wrong kind");
01017   int kind = e.getKind();
01018   DebugAssert(e[0].isRational() && e[0].getRational() == 0,
01019               "TheoryArith::isolateVariable: theorem must be of "
01020               "the form 0 < rhs: " + inputThm.toString());
01021 
01022   const Expr& zero = e[0];
01023   Expr right = e[1];
01024   // Check for trivial in-equation.
01025   if (right.isRational()) {
01026     result = iffMP(result, d_rules->constPredicate(e));
01027     TRACE("arith ineq","isolateVariable => ",result.getExpr()," }");
01028     TRACE("arith","isolateVariable => ",result," }");
01029     return result;
01030   }
01031 
01032   // Normalization of inequality to make coefficients integer and
01033   // relatively prime.
01034 
01035   Expr factor(computeNormalFactor(right));
01036   TRACE("arith", "isolateVariable: factor = ", factor, "");
01037   DebugAssert(factor.getRational() > 0,
01038               "isolateVariable: factor="+factor.toString());
01039   // Now multiply the inequality by the factor, unless it is 1
01040   if(factor.getRational() != 1) {
01041     result = iffMP(result, d_rules->multIneqn(e, factor));
01042     // And canonize the result
01043     result = canonPred(result);
01044     right = result.getExpr()[1];
01045   }
01046 
01047   // Find monomial to isolate and store it in isolatedMonomial
01048   Expr isolatedMonomial = right;
01049 
01050   if (isPlus(right))
01051     isolatedMonomial = pickMonomial(right);
01052 
01053   Rational r = -1;
01054   isolatedVarOnRHS = true;
01055   if (isMult(isolatedMonomial)) {
01056     r = ((isolatedMonomial[0].getRational()) >= 0)? -1 : 1;
01057     isolatedVarOnRHS = 
01058       ((isolatedMonomial[0].getRational()) >= 0)? true : false;
01059   }
01060   isolatedMonomial = canon(rat(-1)*isolatedMonomial).getRHS();
01061   // Isolate isolatedMonomial on to the LHS
01062   result = iffMP(result, d_rules->plusPredicate(zero, right, 
01063                                                 isolatedMonomial, kind));
01064   // Canonize the resulting inequality
01065   result = canonPred(result);
01066   if(1 != r) {
01067     result = iffMP(result, d_rules->multIneqn(result.getExpr(), rat(r)));
01068     result = canonPred(result);
01069   }
01070   TRACE("arith ineq","isolateVariable => ",result.getExpr()," }");
01071   TRACE("arith","isolateVariable => ",result," }");
01072   return result;
01073 }
01074 
01075 Expr
01076 TheoryArith::computeNormalFactor(const Expr& right) {
01077   // Strategy: compute f = lcm(d1...dn)/gcd(c1...cn), where the RHS is
01078   // of the form c1/d1*x1 + ... + cn/dn*xn
01079   Rational factor;
01080   if(isPlus(right)) {
01081     vector<Rational> nums, denoms;
01082     for(int i=0, iend=right.arity(); i<iend; ++i) {
01083       switch(right[i].getKind()) {
01084       case RATIONAL_EXPR: {
01085         Rational c(abs(right[i].getRational()));
01086         nums.push_back(c.getNumerator());
01087         denoms.push_back(c.getDenominator());
01088         break;
01089         }
01090       case MULT: {
01091         Rational c(abs(right[i][0].getRational()));
01092         nums.push_back(c.getNumerator());
01093         denoms.push_back(c.getDenominator());
01094         break;
01095         }
01096       default: // it's a variable
01097         nums.push_back(1);
01098         denoms.push_back(1);
01099         break;
01100       }
01101     }
01102     Rational gcd_nums = gcd(nums);
01103     // x/0 == 0 in our model, as a total extension of arithmetic.  The
01104     // particular value of x/0 is irrelevant, since the DP is guarded
01105     // by the top-level TCCs, and it is safe to return any value in
01106     // cases when terms are undefined.
01107     factor = (gcd_nums==0)? 0 : (lcm(denoms) / gcd_nums);
01108   } else if(isMult(right)) {
01109     const Rational& r = right[0].getRational();
01110     factor = (r==0)? 0 : (1/abs(r));
01111   }
01112   else 
01113     factor = 1;
01114   return rat(factor);
01115 }
01116 
01117 
01118 bool TheoryArith::lessThanVar(const Expr& isolatedMonomial, const Expr& var2) 
01119 {
01120   DebugAssert(!isRational(var2) && !isRational(isolatedMonomial),
01121               "TheoryArith::findMaxVar: isolatedMonomial cannot be rational" + 
01122               isolatedMonomial.toString());
01123   Expr c, var0, var1;
01124   separateMonomial(isolatedMonomial, c, var0);
01125   separateMonomial(var2, c, var1);
01126   return var0 < var1;
01127 }
01128 
01129 /*! "Stale" means it contains non-simplified subexpressions.  For
01130  *  terms, it checks the expression's find pointer; for formulas it
01131  *  checks the children recursively (no caching!).  So, apply it with
01132  *  caution, and only to simple atomic formulas (like inequality).
01133  */
01134 bool TheoryArith::isStale(const Expr& e) {
01135   if(e.isTerm())
01136     return e != find(e).getRHS();
01137   // It's better be a simple predicate (like inequality); we check the
01138   // kids recursively
01139   bool stale=false;
01140   for(Expr::iterator i=e.begin(), iend=e.end(); !stale && i!=iend; ++i)
01141     stale = isStale(*i);
01142   return stale;
01143 }
01144 
01145 
01146 bool TheoryArith::isStale(const TheoryArith::Ineq& ineq) {
01147   TRACE("arith ineq", "isStale(", ineq, ") {");
01148   const Expr& ineqExpr = ineq.ineq().getExpr();
01149   const Rational& c = freeConstIneq(ineqExpr, ineq.varOnRHS());
01150   bool strict(isLT(ineqExpr));
01151   const FreeConst& fc = ineq.getConst();
01152 
01153   bool subsumed;
01154 
01155   if(ineq.varOnRHS()) {
01156     subsumed = (c < fc.getConst() ||
01157                 (c == fc.getConst() && !strict && fc.strict()));
01158   } else {
01159     subsumed = (c > fc.getConst() ||
01160                 (c == fc.getConst() && strict && !fc.strict()));
01161   }
01162 
01163   bool res;
01164   if(subsumed) {
01165     res = true;
01166     TRACE("arith ineq", "isStale[subsumed] => ", res? "true" : "false", " }");
01167   }
01168   else {
01169     res = isStale(ineqExpr);
01170     TRACE("arith ineq", "isStale[updated] => ", res? "true" : "false", " }");
01171   }
01172   return res;
01173 }
01174 
01175 
01176 void TheoryArith::separateMonomial(const Expr& e, Expr& c, Expr& var) {
01177   TRACE("separateMonomial", "separateMonomial(", e, ")");
01178   DebugAssert(!isPlus(e), 
01179               "TheoryArith::separateMonomial(e = "+e.toString()+")");
01180   if(isMult(e)) {
01181     DebugAssert(e.arity() >= 2,
01182                 "TheoryArith::separateMonomial(e = "+e.toString()+")");
01183     c = e[0];
01184     if(e.arity() == 2) var = e[1];
01185     else {
01186       vector<Expr> kids = e.getKids();
01187       kids[0] = rat(1);
01188       var = multExpr(kids);
01189     }
01190   } else {
01191     c = rat(1);
01192     var = e;
01193   }
01194   DebugAssert(c.isRational(), "TheoryArith::separateMonomial(e = "
01195               +e.toString()+", c = "+c.toString()+")");
01196   DebugAssert(!isMult(var) || (var[0].isRational() && var[0].getRational()==1),
01197               "TheoryArith::separateMonomial(e = "
01198               +e.toString()+", var = "+var.toString()+")");
01199 }
01200 
01201 
01202 void TheoryArith::projectInequalities(const Theorem& theInequality, 
01203                                       bool isolatedVarOnRHS)
01204 {
01205   TRACE("arith ineq", "projectInequalities(", theInequality.getExpr(),
01206         ", isolatedVarOnRHS="+string(isolatedVarOnRHS? "true" : "false")
01207         +") {");
01208   DebugAssert(isLE(theInequality.getExpr()) || 
01209               isLT(theInequality.getExpr()),
01210               "TheoryArith::projectIsolatedVar: "\
01211               "theInequality is of the wrong form: " + 
01212               theInequality.toString());
01213   //TODO: DebugAssert to check if the isolatedMonomial is of the right
01214   //form and the whether we are indeed getting inequalities.
01215   Theorem theIneqThm(theInequality);
01216   Expr theIneq = theIneqThm.getExpr();
01217 
01218   Theorem isIntLHS(isIntegerThm(theIneq[0]));
01219   Theorem isIntRHS(isIntegerThm(theIneq[1]));
01220   bool isInt = (!isIntLHS.isNull() && !isIntRHS.isNull());
01221   // If the inequality is strict and integer, change it to non-strict
01222   if(isLT(theIneq) && isInt) {
01223     Theorem thm = d_rules->lessThanToLE(theInequality, isIntLHS, isIntRHS,
01224                                         !isolatedVarOnRHS);
01225     theIneqThm = canonPred(iffMP(theIneqThm, thm));
01226     theIneq = theIneqThm.getExpr();
01227   }
01228   Expr isolatedMonomial = 
01229     isolatedVarOnRHS ? theIneq[1] : theIneq[0];
01230   
01231   Expr monomialVar, a;
01232   separateMonomial(isolatedMonomial, a, monomialVar);
01233 
01234   bool subsumed;
01235   const FreeConst& bestConst =
01236     updateSubsumptionDB(theIneq, isolatedVarOnRHS, subsumed);
01237 
01238   if(subsumed) {
01239     IF_DEBUG(debugger.counter("subsumed inequalities")++);
01240     TRACE("arith ineq", "subsumed inequality: ", theIneq, "");
01241   } else {
01242     // If the isolated variable is actually a non-linear term, we are
01243     // incomplete
01244     if(isMult(monomialVar))
01245       setIncomplete("Non-linear arithmetic inequalities");
01246 
01247     // First, we need to make sure the isolated inequality is
01248     // setup properly.
01249     setupRec(theIneq[0]);
01250     setupRec(theIneq[1]);
01251     // Add the inequality into the appropriate DB.
01252     ExprMap<CDList<Ineq> *>& db1 =
01253       isolatedVarOnRHS ? d_inequalitiesRightDB : d_inequalitiesLeftDB; 
01254     ExprMap<CDList<Ineq> *>::iterator it1 = db1.find(monomialVar);
01255     if(it1 == db1.end()) {
01256       CDList<Ineq> * list = new CDList<Ineq>(theoryCore()->getCM()->getCurrentContext());
01257       list->push_back(Ineq(theIneqThm, isolatedVarOnRHS, bestConst));
01258       db1[monomialVar] = list;
01259     }
01260     else 
01261       ((*it1).second)->push_back(Ineq(theIneqThm, isolatedVarOnRHS, bestConst));
01262   
01263     ExprMap<CDList<Ineq> *>& db2 = 
01264       isolatedVarOnRHS ? d_inequalitiesLeftDB : d_inequalitiesRightDB; 
01265     ExprMap<CDList<Ineq> *>::iterator it = db2.find(monomialVar);
01266     if(it == db2.end()) {
01267       TRACE_MSG("arith ineq", "projectInequalities[not in DB] => }");
01268       return;
01269     }
01270   
01271     CDList<Ineq>& listOfDBIneqs = *((*it).second);
01272     Theorem betaLTt, tLTalpha, thm;
01273     for(size_t i = 0, iend=listOfDBIneqs.size(); i!=iend; ++i) {
01274       const Ineq& ineqEntry = listOfDBIneqs[i];
01275       const Theorem& ineqThm = ineqEntry.ineq();
01276       if(!isStale(ineqEntry)) {
01277         betaLTt = isolatedVarOnRHS ? theIneqThm : ineqThm;
01278         tLTalpha = isolatedVarOnRHS ? ineqThm : theIneqThm;
01279         thm = normalizeProjectIneqs(betaLTt, tLTalpha);
01280         
01281         IF_DEBUG(debugger.counter("real shadows")++);
01282 
01283         // Check for TRUE and FALSE theorems
01284         Expr e(thm.getExpr());  if(e.isFalse()) {
01285           setInconsistent(thm);
01286           TRACE_MSG("arith ineq", "projectInequalities[inconsistent] => }");
01287           return;
01288         }
01289         else {
01290           if(!e.isTrue() && !e.isEq())
01291             addToBuffer(thm);
01292           else if(e.isEq())
01293             enqueueFact(thm);
01294         }
01295       } else {
01296         IF_DEBUG(debugger.counter("stale inequalities")++);
01297       }
01298     }
01299   }
01300   TRACE_MSG("arith ineq", "projectInequalities => }");
01301 }
01302 
01303 Theorem TheoryArith::normalizeProjectIneqs(const Theorem& ineqThm1, 
01304                                            const Theorem& ineqThm2)
01305 {
01306   //ineq1 is of the form beta < b.x  or beta < x  [ or with <= ]
01307   //ineq2 is of the form a.x < alpha   or x < alpha.
01308   Theorem betaLTt = ineqThm1, tLTalpha = ineqThm2;
01309   Expr ineq1 = betaLTt.getExpr();
01310   Expr ineq2 = tLTalpha.getExpr();
01311   Expr c,x;
01312   separateMonomial(ineq2[0], c, x);
01313   Theorem isIntx(isIntegerThm(x));
01314   Theorem isIntBeta(isIntegerThm(ineq1[0]));
01315   Theorem isIntAlpha(isIntegerThm(ineq2[1]));
01316   bool isInt = !(isIntx.isNull() || isIntBeta.isNull() || isIntAlpha.isNull());
01317 
01318   TRACE("arith ineq", "normalizeProjectIneqs(", ineq1,
01319         ", "+ineq2.toString()+") {");
01320   DebugAssert((isLE(ineq1) || isLT(ineq1)) &&
01321               (isLE(ineq2) || isLT(ineq2)),
01322               "TheoryArith::normalizeProjectIneqs: Wrong Kind inputs: " +
01323               ineq1.toString() + ineq2.toString());
01324   DebugAssert(!isPlus(ineq1[1]) && !isPlus(ineq2[0]),
01325               "TheoryArith::normalizeProjectIneqs: Wrong Kind inputs: " +
01326               ineq1.toString() + ineq2.toString());
01327 
01328   //compute the factors to multiply the two inequalities with
01329   //so that they get the form beta < t and t < alpha.
01330   Rational factor1 = 1, factor2 = 1; 
01331   Rational b = isMult(ineq1[1]) ? (ineq1[1])[0].getRational() : 1;
01332   Rational a = isMult(ineq2[0]) ? (ineq2[0])[0].getRational() : 1;
01333   if(b != a) {
01334     factor1 = a;
01335     factor2 = b;
01336   }
01337 
01338   //if the ineqs are of type int then apply one of the gray
01339   //dark shadow rules.
01340   // FIXME: intResult should also be checked for immediate
01341   // optimizations, as those below for 'result'.  Also, if intResult
01342   // is a single inequality, we may want to handle it similarly to the
01343   // 'result' rather than enqueuing directly.
01344   if(isInt && (a >= 2 || b >= 2)) {
01345     Theorem intResult;
01346     if(a <= b)
01347       intResult = d_rules->darkGrayShadow2ab(betaLTt, tLTalpha,
01348                                              isIntAlpha, isIntBeta, isIntx);
01349     else 
01350       intResult = d_rules->darkGrayShadow2ba(betaLTt, tLTalpha,
01351                                              isIntAlpha, isIntBeta, isIntx);
01352     enqueueFact(intResult);
01353     // Fetch dark and gray shadows
01354     DebugAssert(intResult.getExpr().isAnd() && intResult.getExpr().arity()==2,
01355                 "intResult = "+intResult.getExpr().toString());
01356     const Expr& DorG = intResult.getExpr()[0];
01357     DebugAssert(DorG.isOr() && DorG.arity()==2, "DorG = "+DorG.toString());
01358     const Expr& D = DorG[0];
01359     const Expr& G = DorG[1];
01360     DebugAssert(D.getKind()==DARK_SHADOW, "D = "+D.toString());
01361     DebugAssert(G.getKind()==GRAY_SHADOW, "G = "+G.toString());
01362     // Set the higher splitter priority for dark shadow
01363     addSplitter(D, 5);
01364     // Also set a higher priority to the NEGATION of GRAY_SHADOW
01365     addSplitter(!G, 1);
01366     IF_DEBUG(debugger.counter("dark+gray shadows")++);
01367   }
01368 
01369   //actually normalize the inequalities
01370   if(1 != factor1) {
01371     std::vector<Theorem> thms1;
01372     Theorem thm2 = iffMP(betaLTt, d_rules->multIneqn(ineq1, rat(factor1)));
01373     betaLTt = canonPred(thm2);
01374     ineq1 = betaLTt.getExpr();
01375   }
01376   if(1 != factor2) {
01377     std::vector<Theorem> thms1;
01378     Theorem thm2 = iffMP(tLTalpha, d_rules->multIneqn(ineq2, rat(factor2)));
01379     tLTalpha = canonPred(thm2);
01380     ineq2 = tLTalpha.getExpr();
01381   }
01382 
01383   //IF_DEBUG(debugger.counter("real shadows")++);
01384 
01385   Expr beta(ineq1[0]);
01386   Expr alpha(ineq2[1]);
01387   // In case of alpha <= t <= alpha, we generate t = alpha
01388   if(isLE(ineq1) && isLE(ineq2) && alpha == beta) {
01389     Theorem result = d_rules->realShadowEq(betaLTt, tLTalpha);
01390     TRACE("arith ineq", "normalizeProjectIneqs => ", result, " }");
01391     return result;
01392   }
01393 
01394   // Check if this inequality is a finite interval
01395   if(isInt)
01396     processFiniteInterval(betaLTt, tLTalpha);
01397 
01398   //project the normalized inequalities.
01399 
01400   Theorem result = d_rules->realShadow(betaLTt, tLTalpha);
01401 
01402   // FIXME: Clark's changes.  Is 'rewrite' more or less efficient?
01403 //   result = iffMP(result, rewrite(result.getExpr()));
01404 //   TRACE("arith ineq", "normalizeProjectIneqs => ", result, " }");
01405 
01406   // Now, transform the result into 0 < rhs and see if rhs is a const 
01407   Expr e(result.getExpr());
01408   // int kind = e.getKind();
01409   if(!(e[0].isRational() && e[0].getRational() == 0)) {
01410     result = iffMP(result, d_rules->rightMinusLeft(e));
01411     result = canonPred(result);
01412   }
01413   
01414   //result is "0 kind e'". where e' is equal to canon(e[1]-e[0])
01415   Expr right = result.getExpr()[1];
01416   // Check for trivial inequality
01417   if (right.isRational())
01418     result = iffMP(result, d_rules->constPredicate(result.getExpr()));
01419   TRACE("arith ineq", "normalizeProjectIneqs => ", result, " }");
01420   return result;
01421 }
01422 
01423 
01424 Expr TheoryArith::pickMonomial(const Expr& right)
01425 {
01426   DebugAssert(isPlus(right), "TheoryArith::pickMonomial: Wrong Kind: " + 
01427               right.toString());
01428   if(theoryCore()->getFlags()["var-order"].getBool()) {
01429     Expr::iterator i = right.begin();
01430     Expr isolatedMonomial = right[1];
01431     //PLUS always has at least two elements and the first element is
01432     //always a constant. hence ++i in the initialization of the for
01433     //loop.
01434     for(++i; i != right.end(); ++i)
01435       if(lessThanVar(isolatedMonomial,*i))
01436         isolatedMonomial = *i;
01437     return isolatedMonomial;
01438   }
01439   ExprMap<Expr> var2monomial;
01440   vector<Expr> vars;
01441   Expr::iterator i = right.begin(), iend = right.end();
01442   for(;i != iend; ++i) {
01443     if(i->isRational())
01444       continue;
01445     Expr c, var;
01446     separateMonomial(*i, c, var);
01447     var2monomial[var] = *i;
01448     vars.push_back(var);
01449   }
01450   vector<Expr> largest;
01451   d_graph.selectLargest(vars, largest);
01452   DebugAssert(0 < largest.size(),
01453               "TheoryArith::pickMonomial: selectLargest: failed!!!!");
01454   if(1 == largest.size())
01455     return var2monomial[largest[0] ];
01456   else {
01457     size_t pickedVar = 0;
01458     // Pick the variable which will generate the fewest number of
01459     // projections
01460     int minProjections(-1);
01461     for(size_t k=0; k< largest.size(); ++k) {
01462       const Expr& var(largest[k]), monom(var2monomial[var]);
01463       // Grab the counters for the variable
01464       int nRight = (d_countRight.count(var) > 0)? d_countRight[var] : 0;
01465       int nLeft = (d_countLeft.count(var) > 0)? d_countLeft[var] : 0;
01466       int n(nRight*nLeft);
01467       TRACE("arith ineq", "pickMonomial: var=", var,
01468             ", nRight="+int2string(nRight)+", nLeft="+int2string(nLeft));
01469       if(minProjections < 0 || minProjections > n) {
01470         minProjections = n;
01471         pickedVar = k;
01472       }
01473       TRACE("arith ineq", "Number of projections for "+var.toString()+" = ",
01474             n, "");
01475     }
01476     
01477     const Expr& largestVar = largest[pickedVar];
01478     // FIXME: TODO: update the counters (subtract counts for the vars
01479     // other than largestVar
01480 
01481     // Update the graph.
01482     for(size_t k = 0; k < largest.size(); ++k) {
01483       if(k != pickedVar)
01484         d_graph.addEdge(largestVar, largest[k]);
01485     }
01486     return var2monomial[largestVar];
01487   }
01488 }
01489 
01490 void TheoryArith::VarOrderGraph::addEdge(const Expr& e1, const Expr& e2)
01491 {
01492   TRACE("arith var order", "addEdge("+e1.toString()+" > ", e2, ")");
01493   DebugAssert(e1 != e2, "TheoryArith::VarOrderGraph::addEdge("
01494               +e1.toString()+", "+e2.toString()+")");
01495   d_edges[e1].push_back(e2);
01496 }
01497 
01498 //returns true if e1 < e2, else false(i.e e2 < e1 or e1,e2 are not
01499 //comparable)
01500 bool TheoryArith::VarOrderGraph::lessThan(const Expr& e1, const Expr& e2) 
01501 {
01502   d_cache.clear();
01503   //returns true if e1 is in the subtree rooted at e2 implying e1 < e2
01504   return dfs(e1,e2);
01505 }
01506 
01507 //returns true if e1 is in the subtree rooted at e2 implying e1 < e2
01508 bool TheoryArith::VarOrderGraph::dfs(const Expr& e1, const Expr& e2)
01509 {
01510   if(e1 == e2)
01511     return true;
01512   if(d_cache.count(e2) > 0)
01513     return false;
01514   if(d_edges.count(e2) == 0)
01515     return false;
01516   d_cache[e2] = true;
01517   vector<Expr>& e2Edges = d_edges[e2];
01518   vector<Expr>::iterator i = e2Edges.begin();
01519   vector<Expr>::iterator iend = e2Edges.end();
01520   //if dfs finds e1 then i != iend else i is equal to iend
01521   for(; i != iend && !dfs(e1,*i); ++i);
01522   return (i != iend);
01523 }
01524 
01525 
01526 void TheoryArith::VarOrderGraph::selectSmallest(vector<Expr>& v1,
01527                                                vector<Expr>& v2) 
01528 {
01529   int v1Size = v1.size();
01530   vector<bool> v3(v1Size);
01531   for(int j=0; j < v1Size; ++j)
01532     v3[j] = false;
01533 
01534   for(int j=0; j < v1Size; ++j) {
01535     if(v3[j]) continue;
01536     for(int i =0; i < v1Size; ++i) {
01537       if((i == j) || v3[i]) 
01538         continue;
01539       if(lessThan(v1[i],v1[j])) {
01540         v3[j] = true;
01541         break;
01542       }
01543     }
01544   }
01545   vector<Expr> new_v1;
01546 
01547   for(int j = 0; j < v1Size; ++j) 
01548     if(!v3[j]) v2.push_back(v1[j]);
01549     else new_v1.push_back(v1[j]);
01550   v1 = new_v1;
01551 }
01552 
01553 
01554 void TheoryArith::VarOrderGraph::selectLargest(const vector<Expr>& v1,
01555                                                vector<Expr>& v2) 
01556 {
01557   int v1Size = v1.size();
01558   vector<bool> v3(v1Size);
01559   for(int j=0; j < v1Size; ++j)
01560     v3[j] = false;
01561 
01562   for(int j=0; j < v1Size; ++j) {
01563     if(v3[j]) continue;
01564     for(int i =0; i < v1Size; ++i) {
01565       if((i == j) || v3[i]) 
01566         continue;
01567       if(lessThan(v1[j],v1[i])) {
01568         v3[j] = true;
01569         break;
01570       }
01571     }
01572   }
01573   
01574   for(int j = 0; j < v1Size; ++j) 
01575     if(!v3[j]) v2.push_back(v1[j]);
01576 }
01577 
01578 ///////////////////////////////////////////////////////////////////////////////
01579 // TheoryArith Public Methods                                                //
01580 ///////////////////////////////////////////////////////////////////////////////
01581 
01582 
01583 TheoryArith::TheoryArith(VCL* vcl, TheoryCore* core)
01584   : Theory(core, "Arithmetic"),
01585     d_diseq(core->getCM()->getCurrentContext()),
01586     d_diseqIdx(core->getCM()->getCurrentContext(), 0, 0),
01587     d_inModelCreation(core->getCM()->getCurrentContext(), false, 0),
01588     d_realUsed(false), d_intUsed(false), d_intConstUsed(false),
01589     d_langUsed(NOT_USED),
01590     d_convertToDiff(core->getFlags()["convert2diff"].getString()),
01591     d_freeConstDB(core->getCM()->getCurrentContext()),
01592     d_buffer(core->getCM()->getCurrentContext()),
01593     // Initialize index to 0 at scope 0
01594     d_bufferIdx(core->getCM()->getCurrentContext(), 0, 0),
01595     d_bufferThres(&(core->getFlags()["ineq-delay"].getInt())),
01596     d_countRight(core->getCM()->getCurrentContext()),
01597     d_countLeft(core->getCM()->getCurrentContext()),
01598     d_sharedTerms(core->getCM()->getCurrentContext()),
01599     d_sharedVars(core->getCM()->getCurrentContext())
01600 {
01601   IF_DEBUG(d_diseq.setName("CDList[TheoryArith::d_diseq]"));
01602   IF_DEBUG(d_buffer.setName("CDList[TheoryArith::d_buffer]"));
01603   IF_DEBUG(d_bufferIdx.setName("CDList[TheoryArith::d_bufferIdx]"));
01604 
01605   getEM()->newKind(REAL, "REAL", true);
01606   getEM()->newKind(INT, "INT", true);
01607   getEM()->newKind(SUBRANGE, "SUBRANGE", true);
01608 
01609   getEM()->newKind(UMINUS, "UMINUS");
01610   getEM()->newKind(PLUS, "PLUS");
01611   getEM()->newKind(MINUS, "MINUS");
01612   getEM()->newKind(MULT, "MULT");
01613   getEM()->newKind(DIVIDE, "DIVIDE");
01614   getEM()->newKind(POW, "POW");
01615   getEM()->newKind(INTDIV, "INTDIV");
01616   getEM()->newKind(MOD, "MOD");
01617   getEM()->newKind(LT, "LT");
01618   getEM()->newKind(LE, "LE");
01619   getEM()->newKind(GT, "GT");
01620   getEM()->newKind(GE, "GE");
01621   getEM()->newKind(IS_INTEGER, "IS_INTEGER");
01622   getEM()->newKind(NEGINF, "NEGINF");
01623   getEM()->newKind(POSINF, "POSINF");
01624   getEM()->newKind(DARK_SHADOW, "DARK_SHADOW");
01625   getEM()->newKind(GRAY_SHADOW, "GRAY_SHADOW");
01626 
01627   vector<int> kinds;
01628   kinds.push_back(REAL);
01629   kinds.push_back(INT);
01630   kinds.push_back(SUBRANGE);
01631   kinds.push_back(IS_INTEGER);
01632   kinds.push_back(UMINUS);
01633   kinds.push_back(PLUS);
01634   kinds.push_back(MINUS);
01635   kinds.push_back(MULT);
01636   kinds.push_back(DIVIDE);
01637   kinds.push_back(POW);
01638   kinds.push_back(LT);
01639   kinds.push_back(LE);
01640   kinds.push_back(GT);
01641   kinds.push_back(GE);
01642   kinds.push_back(RATIONAL_EXPR);
01643   kinds.push_back(DARK_SHADOW);
01644   kinds.push_back(GRAY_SHADOW);
01645   kinds.push_back(INTDIV);
01646   kinds.push_back(MOD);
01647   kinds.push_back(NEGINF);
01648   kinds.push_back(POSINF);
01649 
01650   registerTheory(this, kinds, true);
01651 
01652   d_realType = Type(getEM()->newLeafExpr(REAL));
01653   d_intType  = Type(getEM()->newLeafExpr(INT));
01654   d_rules = createProofRules();
01655 
01656   // TODO: This is a hack--access to vcl should be hidden here
01657   if (d_convertToDiff == "int") {
01658     d_zeroVar = vcl->varExpr("cvclZero", d_intType);
01659   }
01660   else if (d_convertToDiff == "real") {
01661     d_zeroVar = vcl->varExpr("cvclZero",d_realType);
01662   }
01663 }
01664 
01665 
01666 // Destructor: delete the proof rules class if it's present
01667 TheoryArith::~TheoryArith() {
01668   if(d_rules != NULL) delete d_rules;
01669   // Clear the inequality databases
01670   for(ExprMap<CDList<Ineq> *>::iterator i=d_inequalitiesRightDB.begin(),
01671         iend=d_inequalitiesRightDB.end(); i!=iend; ++i)
01672     delete (i->second);
01673   for(ExprMap<CDList<Ineq> *>::iterator i=d_inequalitiesLeftDB.begin(),
01674         iend=d_inequalitiesLeftDB.end(); i!=iend; ++i)
01675     delete (i->second);
01676 }
01677 
01678 void TheoryArith::collectVars(const Expr& e, vector<Expr>& vars,
01679                               set<Expr>& cache) {
01680   // Check the cache first
01681   if(cache.count(e) > 0) return;
01682   // Not processed yet.  Cache the expression and proceed
01683   cache.insert(e);
01684   if(isLeaf(e)) vars.push_back(e);
01685   else
01686     for(Expr::iterator i=e.begin(), iend=e.end(); i!=iend; ++i)
01687       collectVars(*i, vars, cache);
01688 }
01689 
01690 void
01691 TheoryArith::processFiniteInterval(const Theorem& alphaLEax,
01692                                    const Theorem& bxLEbeta) {
01693   const Expr& ineq1(alphaLEax.getExpr());
01694   const Expr& ineq2(bxLEbeta.getExpr());
01695   DebugAssert(isLE(ineq1), "TheoryArith::processFiniteInterval: ineq1 = "
01696               +ineq1.toString());
01697   DebugAssert(isLE(ineq2), "TheoryArith::processFiniteInterval: ineq2 = "
01698               +ineq2.toString());
01699   // If the inequalities are not integer, just return (nothing to do)
01700   if(!isInteger(ineq1[0])
01701      || !isInteger(ineq1[1])
01702      || !isInteger(ineq2[0])
01703      || !isInteger(ineq2[1]))
01704     return;
01705 
01706   const Expr& ax = ineq1[1];
01707   const Expr& bx = ineq2[0];
01708   DebugAssert(!isPlus(ax) && !isRational(ax),
01709               "TheoryArith::processFiniteInterval:\n ax = "+ax.toString());
01710   DebugAssert(!isPlus(bx) && !isRational(bx),
01711               "TheoryArith::processFiniteInterval:\n bx = "+bx.toString());
01712   Expr a = isMult(ax)? ax[0] : rat(1);
01713   Expr b = isMult(bx)? bx[0] : rat(1);
01714 
01715   Theorem thm1(alphaLEax), thm2(bxLEbeta);
01716   // Multiply the inequalities by 'b' and 'a', and canonize them, if necessary
01717   if(a != b) {
01718     thm1 = canonPred(iffMP(alphaLEax, d_rules->multIneqn(ineq1, b)));
01719     thm2 = canonPred(iffMP(bxLEbeta, d_rules->multIneqn(ineq2, a)));
01720   }
01721   // Check that a*beta - b*alpha == c > 0
01722   const Expr& alphaLEt = thm1.getExpr();
01723   const Expr& alpha = alphaLEt[0];
01724   const Expr& t = alphaLEt[1];
01725   const Expr& beta = thm2.getExpr()[1];
01726   Expr c = canon(beta - alpha).getRHS();
01727 
01728   if(c.isRational() && c.getRational() >= 1) {
01729     // This is a finite interval.  First, derive t <= alpha + c:
01730     // canon(alpha+c) => (alpha+c == beta) ==> [symmetry] beta == alpha+c
01731     // Then substitute that in thm2
01732     Theorem bEQac = symmetryRule(canon(alpha + c));
01733     // Substitute beta == alpha+c for the second child of thm2
01734     vector<unsigned> changed;
01735     vector<Theorem> thms;
01736     changed.push_back(1);
01737     thms.push_back(bEQac);
01738     Theorem tLEac = substitutivityRule(thm2.getExpr(), changed, thms);
01739     tLEac = iffMP(thm2, tLEac);
01740     // Derive and enqueue the finite interval constraint
01741     Theorem isInta(isIntegerThm(alpha));
01742     Theorem isIntt(isIntegerThm(t));
01743     enqueueFact(d_rules->finiteInterval(thm1, tLEac, isInta, isIntt));
01744   }
01745 }
01746 
01747 
01748 void
01749 TheoryArith::processFiniteIntervals(const Expr& x) {
01750   // If x is not integer, do not bother
01751   if(!isInteger(x)) return;
01752   // Process every pair of the opposing inequalities for 'x'
01753   ExprMap<CDList<Ineq> *>::iterator iLeft, iRight;
01754   iLeft = d_inequalitiesLeftDB.find(x);
01755   if(iLeft == d_inequalitiesLeftDB.end()) return;
01756   iRight = d_inequalitiesRightDB.find(x);
01757   if(iRight == d_inequalitiesRightDB.end()) return;
01758   // There are some opposing inequalities; get the lists
01759   CDList<Ineq>& ineqsLeft = *(iLeft->second);
01760   CDList<Ineq>& ineqsRight = *(iRight->second);
01761   // Get the sizes of the lists
01762   size_t sizeLeft = ineqsLeft.size();
01763   size_t sizeRight = ineqsRight.size();
01764   // Process all the pairs of the opposing inequalities
01765   for(size_t l=0; l<sizeLeft; ++l)
01766     for(size_t r=0; r<sizeRight; ++r)
01767       processFiniteInterval(ineqsRight[r], ineqsLeft[l]);
01768 }
01769 
01770 /*! This function recursively decends expression tree <strong>without
01771  *  caching</strong> until it hits a node that is already setup.  Be
01772  *  careful on what expressions you are calling it.
01773  */
01774 void
01775 TheoryArith::setupRec(const Expr& e) {
01776   if(e.hasFind()) return;
01777   // First, set up the kids recursively
01778   for (int k = 0; k < e.arity(); ++k) {
01779     setupRec(e[k]);
01780   }
01781   // Create a find pointer for e
01782   e.setFind(reflexivityRule(e));
01783   // And call our own setup()   
01784   setup(e);
01785 }
01786 
01787 
01788 /*!
01789  * Keep track of all finitely bounded integer variables in shared
01790  * terms.
01791  *
01792  * When a new shared term t is reported, all of its variables x1...xn
01793  * are added to the set d_sharedVars.  
01794  *
01795  * For each newly added variable x, check all of its opposing
01796  * inequalities, find out all the finite bounds and assert the
01797  * corresponding GRAY_SHADOW constraints.
01798  *
01799  * When projecting integer inequalities, the database d_sharedVars is
01800  * consulted, and if the variable is in it, check the shadows for
01801  * being a finite interval, and produce the additional GRAY_SHADOW
01802  * constraints.
01803  */
01804 void TheoryArith::addSharedTerm(const Expr& e) {
01805   d_sharedTerms[e] = true;
01806   /*
01807   set<Expr> cache; // Aux. cache for collecting i-leaves
01808   vector<Expr> vars; // Vector of vars in e
01809   collectVars(e, vars, cache);
01810   for(vector<Expr>::iterator i=vars.begin(), iend=vars.end(); i!=iend; ++i) {
01811     if(d_sharedVars.count(*i) == 0) {
01812       TRACE("arith shared", "TheoryArith::addSharedTerm: new var = ", *i, "");
01813       processFiniteIntervals(*i);
01814       d_sharedVars[*i]=true;
01815     }
01816   }
01817   */
01818 }
01819 
01820 
01821 void TheoryArith::assertFact(const Theorem& e)
01822 {
01823   const Expr& expr = e.getExpr();
01824   if (expr.isNot() && expr[0].isEq()) {
01825     IF_DEBUG(debugger.counter("[arith] received disequalities")++);
01826     d_diseq.push_back(e);
01827   }
01828   else if (!expr.isEq()){
01829     if (expr.isNot()) {
01830       // This can only be negation of dark or gray shadows, or
01831       // disequalities, which we ignore.  Negations of inequalities
01832       // are handled in rewrite, we don't even receive them here.
01833     } 
01834     else if(isDarkShadow(expr)) {
01835       enqueueFact(d_rules->expandDarkShadow(e));
01836       IF_DEBUG(debugger.counter("received DARK_SHADOW")++);
01837     }
01838     else if(isGrayShadow(expr)) {
01839       IF_DEBUG(debugger.counter("received GRAY_SHADOW")++);
01840       const Rational& c1 = expr[2].getRational();
01841       const Rational& c2 = expr[3].getRational();
01842       const Expr& v = expr[0];
01843       const Expr& ee = expr[1];
01844       if(c1 == c2)
01845         enqueueFact(d_rules->expandGrayShadow0(e));
01846       else {
01847         Theorem gThm(e);
01848         // Check if we can reduce the number of cases in G(ax,c,c1,c2)
01849         if(ee.isRational() && isMult(v)
01850            && v[0].isRational() && v[0].getRational() >= 2) {
01851           IF_DEBUG(debugger.counter("reduced const GRAY_SHADOW")++);
01852           gThm = d_rules->grayShadowConst(e);
01853         }
01854         // (Possibly) new gray shadow
01855         const Expr& g = gThm.getExpr();
01856         if(g.isFalse())
01857           setInconsistent(gThm);
01858         else if(g[2].getRational() == g[3].getRational())
01859           enqueueFact(d_rules->expandGrayShadow0(gThm));
01860         else {
01861           // Assert c1+e <= v <= c2+e
01862           enqueueFact(d_rules->expandGrayShadow(gThm));
01863           // Split G into 2 cases (binary search b/w c1 and c2)
01864           Theorem thm2 = d_rules->splitGrayShadow(gThm);
01865           enqueueFact(thm2);
01866           // Fetch the two gray shadows
01867           DebugAssert(thm2.getExpr().isAnd() && thm2.getExpr().arity()==2,
01868                       "thm2 = "+thm2.getExpr().toString());
01869           const Expr& G1orG2 = thm2.getExpr()[0];
01870           DebugAssert(G1orG2.isOr() && G1orG2.arity()==2,
01871                       "G1orG2 = "+G1orG2.toString());
01872           const Expr& G1 = G1orG2[0];
01873           const Expr& G2 = G1orG2[1];
01874           DebugAssert(G1.getKind()==GRAY_SHADOW, "G1 = "+G1.toString());
01875           DebugAssert(G2.getKind()==GRAY_SHADOW, "G2 = "+G2.toString());
01876           // Split on the left disjunct first (keep the priority low)
01877           addSplitter(G1, 1);
01878           addSplitter(G2, -1);
01879         }
01880       }
01881     }
01882     else {
01883       DebugAssert(isLE(expr) || isLT(expr) || isIntPred(expr), 
01884                   "expected LE or LT: "+expr.toString());
01885       if(isLE(expr) || isLT(expr)) {
01886         IF_DEBUG(debugger.counter("recevied inequalities")++);
01887         
01888         // Buffer the inequality
01889         addToBuffer(e);
01890         
01891         TRACE("arith ineq", "buffer.size() = ", d_buffer.size(), 
01892               ", index="+int2string(d_bufferIdx)
01893               +", threshold="+int2string(*d_bufferThres));
01894         
01895         if((((int)d_buffer.size()) - (int)d_bufferIdx > *d_bufferThres) 
01896            && !d_inModelCreation)
01897           processBuffer();
01898       } else {
01899         IF_DEBUG(debugger.counter("arith IS_INTEGER")++);
01900       }
01901     }
01902   }
01903   else {
01904     IF_DEBUG(debugger.counter("[arith] received t1=t2")++);
01905   }
01906 }
01907 
01908 
01909 void TheoryArith::checkSat(bool fullEffort)
01910 {
01911   //  vector<Expr>::const_iterator e;
01912   //  vector<Expr>::const_iterator eEnd;
01913   // TODO: convert back to use iterators
01914   TRACE("arith ineq", "TheoryArith::checkSat(fullEffort=",
01915         fullEffort? "true" : "false", ")");
01916   if (fullEffort) {
01917     while(!inconsistent() && d_bufferIdx < d_buffer.size())
01918       processBuffer();
01919     if(d_inModelCreation) {
01920       for(; d_diseqIdx < d_diseq.size(); d_diseqIdx = d_diseqIdx+1) {
01921         TRACE("model", "[arith] refining diseq: ",
01922               d_diseq[d_diseqIdx].getExpr() , "");    
01923         enqueueFact(d_rules->diseqToIneq(d_diseq[d_diseqIdx]));
01924       }
01925     }
01926   }
01927 }
01928 
01929 
01930 
01931 void TheoryArith::refineCounterExample()
01932 {
01933   d_inModelCreation = true;
01934   TRACE("model", "refineCounterExample[TheoryArith] ", "", "{");
01935   CDMap<Expr, bool>::iterator it = d_sharedTerms.begin(), it2,
01936     iend = d_sharedTerms.end();
01937   // Add equalities over all pairs of shared terms as suggested
01938   // splitters.  Notice, that we want to split on equality
01939   // (positively) first, to reduce the size of the model.
01940   for(; it!=iend; ++it) {
01941     // Copy by value: the elements in the pair from *it are NOT refs in CDMap
01942     Expr e1 = (*it).first;
01943     for(it2 = it, ++it2; it2!=iend; ++it2) {
01944       Expr e2 = (*it2).first;
01945       DebugAssert(isReal(getBaseType(e1)),
01946                   "TheoryArith::refineCounterExample: e1 = "+e1.toString()
01947                   +"\n type(e1) = "+e1.getType().toString());
01948       if(findExpr(e1) != findExpr(e2)) {
01949         DebugAssert(isReal(getBaseType(e2)),
01950                     "TheoryArith::refineCounterExample: e2 = "+e2.toString()
01951                     +"\n type(e2) = "+e2.getType().toString());
01952         Expr eq = e1.eqExpr(e2);
01953         addSplitter(eq);
01954       }
01955     }
01956   }
01957   TRACE("model", "refineCounterExample[Theory::Arith] ", "", "}");
01958 }
01959 
01960 
01961 void
01962 TheoryArith::findRationalBound(const Expr& varSide, const Expr& ratSide, 
01963                                const Expr& var,
01964                                Rational &r)
01965 {
01966   Expr c, x;
01967   separateMonomial(varSide, c, x);
01968   
01969   DebugAssert(findExpr(c).isRational(), 
01970               "seperateMonomial failed"); 
01971   DebugAssert(findExpr(ratSide).isRational(), 
01972               "smallest variable in graph, should not have variables"
01973               " in inequalities: ");
01974   DebugAssert(x == var, "separateMonomial found different variable: " 
01975               + var.toString());
01976   r = findExpr(ratSide).getRational() / findExpr(c).getRational();
01977 } 
01978 
01979 bool
01980 TheoryArith::findBounds(const Expr& e, Rational& lub, Rational&  glb)
01981 {
01982   bool strictLB=false, strictUB=false;
01983   bool right = (d_inequalitiesRightDB.count(e) > 0
01984                        && d_inequalitiesRightDB[e]->size() > 0);
01985   bool left = (d_inequalitiesLeftDB.count(e) > 0
01986                && d_inequalitiesLeftDB[e]->size() > 0);
01987   int numRight = 0, numLeft = 0;
01988   if(right) { //rationals less than e
01989     CDList<Ineq> * ratsLTe = d_inequalitiesRightDB[e];
01990     for(unsigned int i=0; i<ratsLTe->size(); i++) {
01991       DebugAssert((*ratsLTe)[i].varOnRHS(), "variable on wrong side!");
01992       Expr ineq = (*ratsLTe)[i].ineq().getExpr();
01993       Expr leftSide = ineq[0], rightSide = ineq[1];
01994       Rational r;
01995       findRationalBound(rightSide, leftSide, e , r);
01996       if(numRight==0 || r>glb){
01997         glb = r;
01998         strictLB = isLT(ineq);
01999       }
02000       numRight++;
02001     }
02002     TRACE("model", "   =>Lower bound ", glb.toString(), "");
02003   }
02004   if(left) {   //rationals greater than e
02005     CDList<Ineq> * ratsGTe = d_inequalitiesLeftDB[e];
02006     for(unsigned int i=0; i<ratsGTe->size(); i++) { 
02007       DebugAssert((*ratsGTe)[i].varOnLHS(), "variable on wrong side!");
02008       Expr ineq = (*ratsGTe)[i].ineq().getExpr();
02009       Expr leftSide = ineq[0], rightSide = ineq[1];
02010       Rational r;
02011       findRationalBound(leftSide, rightSide, e, r); 
02012       if(numLeft==0 || r<lub) {
02013         lub = r;
02014         strictUB = isLT(ineq);
02015       }
02016       numLeft++;
02017     }
02018     TRACE("model", "   =>Upper bound ", lub.toString(), "");
02019   }
02020   if(!left && !right) {
02021       lub = 0; 
02022       glb = 0;
02023   }
02024   if(!left && right) {lub = glb +2;}
02025   if(!right && left)  {glb =  lub-2;}
02026   DebugAssert(glb <= lub, "Greatest lower bound needs to be smaller "
02027               "than least upper bound"); 
02028   return strictLB;
02029 }
02030 
02031 void TheoryArith::assignVariables(std::vector<Expr>&v)
02032 {
02033   int count = 0;
02034   while (v.size() > 0) {
02035     std::vector<Expr> bottom;
02036     d_graph.selectSmallest(v, bottom);
02037     TRACE("model", "Finding variables to assign. Iteration # ", count, "");
02038     for(unsigned int i = 0; i<bottom.size(); i++) {
02039       Expr e = bottom[i];
02040       TRACE("model", "Found: ", e, "");
02041       // Check if it is already a concrete constant
02042       if(e.isRational()) continue;
02043       
02044       Rational lub, glb;
02045       bool strictLB;
02046       strictLB = findBounds(e, lub, glb);
02047       Rational mid;
02048       if(isInteger(e)) {
02049         if(strictLB && glb.isInteger())
02050           mid = glb + 1;
02051         else
02052           mid = ceil(glb);
02053       }
02054       else
02055         mid = (lub + glb)/2;
02056       TRACE("model", "Assigning mid = ", mid, " {");
02057       assignValue(e, rat(mid));
02058       TRACE("model", "Assigned find(e) = ", findExpr(e), " }");
02059       if(inconsistent()) return; // Punt immediately if failed
02060     }
02061     count++;
02062   }
02063 }
02064 
02065 void TheoryArith::computeModelBasic(const std::vector<Expr>& v)
02066 {
02067   d_inModelCreation = true;
02068   vector<Expr> reps;
02069   TRACE("model", "Arith=>computeModel ", "", "{");
02070   for(unsigned int i=0; i <v.size(); ++i) {
02071     const Expr& e = v[i];
02072     if(findExpr(e) == e) {
02073       TRACE("model", "arith variable:", e , "");
02074       reps.push_back(e);
02075     }
02076     else {
02077       TRACE("model", "arith variable:", e , "");
02078       TRACE("model", " ==> is defined by: ", findExpr(e) , "");
02079     }
02080   }
02081   assignVariables(reps);
02082   TRACE("model", "Arith=>computeModel", "", "}");
02083   d_inModelCreation = false;
02084 }
02085 
02086 // For any arith expression 'e', if the subexpressions are assigned
02087 // concrete values, then find(e) must already be a concrete value.
02088 void TheoryArith::computeModel(const Expr& e, vector<Expr>& vars) {
02089   DebugAssert(findExpr(e).isRational(), "TheoryArith::computeModel("
02090               +e.toString()+")\n e is not assigned concrete value.\n"
02091               +" find(e) = "+findExpr(e).toString());
02092   assignValue(simplify(e));
02093   vars.push_back(e);
02094 }
02095 
02096 
02097 
02098 /*! accepts a rewrite theorem over eqn|ineqn and normalizes it
02099  *  and returns a theorem to that effect. assumes e is non-trivial
02100  *  i.e. e is not '0=const' or 'const=0' or '0 <= const' etc.
02101  */
02102 Theorem TheoryArith::normalize(const Expr& e) {
02103   //e is an eqn or ineqn. e is not a trivial eqn or ineqn
02104   //trivial means 0 = const or 0 <= const.
02105   TRACE("arith", "normalize(", e, ") {");
02106   DebugAssert(e.isEq() || isIneq(e),
02107               "normalize: input must be Eq or Ineq: " + e.toString());
02108   DebugAssert(!isIneq(e) || (0 == e[0].getRational()),
02109               "normalize: if (e is ineq) then e[0] must be 0" +
02110               e.toString());
02111   if(e.isEq()) {
02112     if(e[0].isRational()) {
02113       DebugAssert(0 == e[0].getRational(),
02114                   "normalize: if e is Eq and e[0] is rat then e[0]==0");
02115     }
02116     else {
02117       //if e[0] is not rational then e[1] must be rational.
02118       DebugAssert(e[1].isRational() && 0 == e[1].getRational(),
02119                   "normalize: if e is Eq and e[1] is rat then e[1]==0\n"
02120                   " e = "+e.toString());
02121     }
02122   }
02123   
02124   Expr factor;
02125   if(e[0].isRational())
02126     factor = computeNormalFactor(e[1]);
02127   else
02128     factor = computeNormalFactor(e[0]);
02129   
02130   TRACE("arith", "normalize: factor = ", factor, "");
02131   DebugAssert(factor.getRational() > 0,
02132               "normalize: factor="+ factor.toString());
02133   
02134   Theorem thm(reflexivityRule(e));
02135   // Now multiply the equality by the factor, unless it is 1
02136   if(factor.getRational() != 1) {
02137     int kind = e.getKind();
02138     switch(kind) {
02139     case EQ:
02140       thm = d_rules->multEqn(e[0], e[1], factor);
02141       // And canonize the result
02142       thm = canonPredEquiv(thm);
02143       break;
02144     case LE:
02145     case LT:
02146     case GE:
02147     case GT:
02148       thm = d_rules->multIneqn(e, factor);
02149       // And canonize the result
02150       thm = canonPredEquiv(thm);
02151       break;
02152     default:
02153       DebugAssert(false,
02154                   "normalize: control should not reach here" + kind);
02155       break;
02156     }
02157   }
02158   TRACE("arith", "normalize => ", thm, " }");
02159   return(thm);
02160 }
02161 
02162 
02163 Theorem TheoryArith::normalize(const Theorem& eIffEqn) {
02164   return transitivityRule(eIffEqn, normalize(eIffEqn.getRHS()));
02165 }
02166 
02167 
02168 Theorem TheoryArith::rewrite(const Expr& e)
02169 {
02170   TRACE("arith", "TheoryArith::rewrite(", e, ") {");
02171   Theorem thm;
02172   if (!e.isTerm()) {
02173     if (!e.isAbsLiteral()) {
02174       e.setRewriteNormal();
02175       thm = reflexivityRule(e);
02176       TRACE("arith", "TheoryArith::rewrite[non-literal] => ", thm, " }");
02177       return thm;
02178     }
02179     switch(e.getKind()) {
02180     case EQ:
02181     {
02182       // canonical form for an equality of two leaves
02183       // is just l == r instead of 0 + (-1 * l) + r = 0.
02184       if (isLeaf(e[0]) && isLeaf(e[1]))
02185         thm = reflexivityRule(e);
02186       else { // Otherwise, it is "lhs = 0"
02187         //first convert e to the form 0=e'
02188         if((e[0].isRational() && e[0].getRational() == 0)
02189            || (e[1].isRational() && e[1].getRational() == 0))
02190           //already in 0=e' or e'=0 form
02191           thm = reflexivityRule(e);
02192         else {
02193           thm = d_rules->rightMinusLeft(e);
02194           thm = canonPredEquiv(thm);
02195         }
02196         // Check for trivial equation
02197         if ((thm.getRHS())[0].isRational() && (thm.getRHS())[1].isRational()) {
02198           thm = transitivityRule(thm, d_rules->constPredicate(thm.getRHS()));
02199         } else {
02200           //else equation is non-trivial
02201           thm = normalize(thm);
02202           // Normalization may yield non-simplified terms
02203           thm = canonPredEquiv(thm);
02204 
02205         }
02206       }
02207 
02208       // Equations must be oriented such that lhs >= rhs as Exprs;
02209       // this ordering is given by operator<(Expr,Expr).
02210       const Expr& eq = thm.getRHS();
02211       if(eq.isEq() && eq[0] < eq[1])
02212         thm = transitivityRule(thm, getCommonRules()->rewriteUsingSymmetry(eq));
02213     }
02214     break;
02215     case GRAY_SHADOW:
02216     case DARK_SHADOW:
02217       thm = reflexivityRule(e);
02218       break;
02219     case IS_INTEGER: {
02220       Theorem res(isIntegerDerive(e, typePred(e[0])));
02221       if(!res.isNull())
02222         thm = getCommonRules()->iffTrue(res);
02223       else 
02224         thm = reflexivityRule(e);
02225       break;
02226     }
02227     case NOT:    
02228       if (!isIneq(e[0]))
02229         //in this case we have "NOT of DARK or GRAY_SHADOW."
02230         thm = reflexivityRule(e);
02231       else {
02232         //In this case we have the "NOT of ineq". get rid of NOT
02233         //and then treat like an ineq
02234         thm = d_rules->negatedInequality(e);
02235         DebugAssert(isGE(thm.getRHS()) || isGT(thm.getRHS()),
02236                     "Expected GE or GT");
02237         thm = transitivityRule(thm, d_rules->flipInequality(thm.getRHS()));
02238         thm = transitivityRule(thm, d_rules->rightMinusLeft(thm.getRHS()));
02239         thm = canonPredEquiv(thm);
02240 
02241         // Check for trivial inequation
02242         if ((thm.getRHS())[1].isRational())
02243           thm = transitivityRule(thm, d_rules->constPredicate(thm.getRHS()));
02244         else {
02245           //else ineq is non-trivial
02246           thm = normalize(thm);
02247           // Normalization may yield non-simplified terms
02248           thm = canonPredEquiv(thm);
02249         }
02250       }
02251       break;
02252     case LE:
02253     case LT:
02254     case GE:
02255     case GT:
02256       if (isGE(e) || isGT(e)) {
02257         thm = d_rules->flipInequality(e);
02258         thm = transitivityRule(thm, d_rules->rightMinusLeft(thm.getRHS()));
02259       }
02260       else 
02261         thm = d_rules->rightMinusLeft(e);
02262       thm = canonPredEquiv(thm);
02263    
02264       // Check for trivial inequation
02265       if ((thm.getRHS())[1].isRational()) 
02266         thm = transitivityRule(thm, d_rules->constPredicate(thm.getRHS()));
02267       else { // ineq is non-trivial
02268         thm = normalize(thm);
02269         thm = canonPredEquiv(thm);
02270       }
02271       break;
02272     default:
02273       DebugAssert(false,
02274                   "Theory_Arith::rewrite: control should not reach here");
02275       break;
02276     }
02277   }
02278   else {
02279     if (e.isAtomic())
02280       thm = canon(e);
02281     // Do we still need to simplify? Now that assertEqualities() has a
02282     // queue and we can safely assume that all children of e are
02283     // canonized at this point...
02284     //
02285     //      thm = canonSimplify(e);
02286     else 
02287       thm = reflexivityRule(e);
02288   }
02289   // Arith canonization is idempotent
02290   thm.getRHS().setRewriteNormal();
02291   TRACE("arith", "TheoryArith::rewrite => ", thm, " }");
02292   return thm;
02293 }
02294 
02295 
02296 void TheoryArith::setup(const Expr& e)
02297 {
02298   if (!e.isTerm()) {
02299     if (e.isNot() || e.isEq() || isDarkShadow(e) || isGrayShadow(e)) return;
02300     if(e.getKind() == IS_INTEGER) {
02301       e[0].addToNotify(this, e);
02302       return;
02303     }
02304     DebugAssert((isLT(e)||isLE(e)) &&
02305                 e[0].isRational() && e[0].getRational() == 0,
02306                 "TheoryArith::setup: expected 0 < rhs:" + e.toString());
02307     e[1].addToNotify(this, e);
02308     return;
02309   }
02310   int k(0), ar(e.arity());
02311   for ( ; k < ar; ++k) {
02312     e[k].addToNotify(this, e);
02313     TRACE("arith setup", "e["+int2string(k)+"]: ", *(e[k].getNotify()), "");
02314   }
02315 }
02316 
02317 
02318 void TheoryArith::update(const Theorem& e, const Expr& d)
02319 {
02320   if (inconsistent()) return;
02321   IF_DEBUG(debugger.counter("arith update total")++);
02322   if (!d.hasFind()) return;
02323   if (isIneq(d)) {
02324     // Substitute e[1] for e[0] in d and enqueue new inequality
02325     DebugAssert(e.getLHS() == d[1], "Mismatch");
02326     Theorem thm = find(d);
02327     //    DebugAssert(thm.getRHS() == trueExpr(), "Expected find = true");
02328     vector<unsigned> changed;
02329     vector<Theorem> children;
02330     changed.push_back(1);
02331     children.push_back(e);
02332     Theorem thm2 = substitutivityRule(d, changed, children);
02333     if (thm.getRHS() == trueExpr()) {
02334       enqueueFact(iffMP(getCommonRules()->iffTrueElim(thm), thm2));
02335     }
02336     else {
02337       enqueueFact(getCommonRules()->iffFalseElim(
02338         transitivityRule(symmetryRule(thm2), thm)));
02339     }
02340     IF_DEBUG(debugger.counter("arith update ineq")++);
02341   }
02342   else if (find(d).getRHS() == d) {
02343     // Substitute e[1] for e[0] in d and assert the result equal to d
02344     Theorem thm = updateHelper(d);
02345     TRACE("arith", "TheoryArith::update(): thm = ", thm, "");
02346     // This no longer holds, due to array theory violating the global invariant
02347 //     DebugAssert(leavesAreSimp(thm.getRHS()), "updateHelper error: "
02348 //              +thm.getExpr().toString());
02349     enqueueEquality(transitivityRule(thm, rewrite(thm.getRHS())));
02350 //     for (int k(0), ar(d.arity()); k < ar; ++k)
02351 //       d[k].removeFromNotify(this, d);
02352     IF_DEBUG(debugger.counter("arith update find(d)=d")++);
02353   } else {
02354     // We need to update expressions that haven't yet been updated.
02355     // FIXME: delete 'd' from notify list, once this functionality is
02356     // merged to the main trunk
02357     Theorem thm = updateHelper(d);
02358     TRACE("arith", "TheoryArith::update()[non-rep]: thm = ", thm, "");
02359     enqueueFact(thm);
02360 //     for (int k(0), ar(d.arity()); k < ar; ++k)
02361 //       d[k].removeFromNotify(this, d);
02362     IF_DEBUG(debugger.counter("arith update find(d)!=d")++);
02363   }
02364 }
02365 
02366 
02367 Theorem TheoryArith::solve(const Theorem& thm)
02368 {
02369   const Expr& e = thm.getExpr();
02370   DebugAssert(e.isEq(), "");
02371 
02372   // Check for already solved equalities.
02373 
02374   // Have to be careful about the types: integer variable cannot be
02375   // assigned a real term.  Also, watch for e[0] being a subexpression
02376   // of e[1]: this would create an unsimplifiable expression.
02377   if (isLeaf(e[0]) && !isLeafIn(e[0], e[1]) 
02378       && (!isInteger(e[0]) || isInteger(e[1]))
02379       // && !e[0].subExprOf(e[1])
02380       )
02381     return thm;
02382 
02383   // Symmetric version is already solved
02384   if (isLeaf(e[1]) && !isLeafIn(e[1], e[0])
02385       && (isInteger(e[0]) || !isInteger(e[1]))
02386       // && !e[1].subExprOf(e[0])
02387       )
02388     return symmetryRule(thm);
02389 
02390   return doSolve(thm);
02391 }
02392 
02393 
02394 void TheoryArith::computeModelTerm(const Expr& e, std::vector<Expr>& v) {
02395   switch(e.getKind()) {
02396   case RATIONAL_EXPR: // Skip the constants
02397     break;
02398   case PLUS:
02399   case MULT:
02400   case DIVIDE:
02401   case POW: // This is not a variable; extract the variables from children
02402     for(Expr::iterator i=e.begin(), iend=e.end(); i!=iend; ++i)
02403       // getModelTerm(*i, v);
02404       v.push_back(*i);
02405     break;
02406   default: { // Otherwise it's a variable.  Check if it has a find pointer
02407     Expr e2(findExpr(e));
02408     if(e==e2) {
02409       TRACE("model", "TheoryArith::computeModelTerm(", e, "): a variable");
02410       // Leave it alone (it has no descendants)
02411       // v.push_back(e);
02412     } else {
02413       TRACE("model", "TheoryArith::computeModelTerm("+e.toString()
02414             +"): has find pointer to ", e2, "");
02415       v.push_back(e2);
02416     }
02417   }
02418   }
02419 }
02420 
02421 
02422 Expr TheoryArith::computeTypePred(const Type& t, const Expr& e) {
02423   Expr tExpr = t.getExpr();
02424   switch(tExpr.getKind()) {
02425   case INT:  
02426     return Expr(IS_INTEGER, e);
02427   case SUBRANGE: {
02428     std::vector<Expr> kids;
02429     kids.push_back(Expr(IS_INTEGER, e));
02430     kids.push_back(leExpr(tExpr[0], e));
02431     kids.push_back(leExpr(e, tExpr[1]));
02432     return andExpr(kids);
02433   }
02434   default:
02435     return e.getEM()->trueExpr();
02436   }
02437 }
02438 
02439 
02440 void TheoryArith::checkType(const Expr& e)
02441 {
02442   switch (e.getKind()) {
02443     case INT:
02444     case REAL:
02445       if (e.arity() > 0) {
02446         throw Exception("Ill-formed arithmetic type: "+e.toString());
02447       }
02448       break;
02449     case SUBRANGE:
02450       if (e.arity() != 2 ||
02451           !isIntegerConst(e[0]) ||
02452           !isIntegerConst(e[1]) ||
02453           e[0].getRational() > e[1].getRational()) {
02454         throw Exception("bad SUBRANGE type expression"+e.toString());
02455       }
02456       break;
02457     default:
02458       DebugAssert(false, "Unexpected kind in TheoryArith::checkType"
02459                   +getEM()->getKindName(e.getKind()));
02460   }
02461 }
02462 
02463 
02464 void TheoryArith::computeType(const Expr& e)
02465 {
02466   switch (e.getKind()) {
02467   case RATIONAL_EXPR:
02468       if(e.getRational().isInteger())
02469         e.setType(d_intType);
02470       else
02471         e.setType(d_realType);
02472       break;
02473   case UMINUS:
02474   case PLUS:
02475   case MINUS:
02476   case MULT:
02477   case POW: {
02478     bool isInt = true;
02479     for(int k = 0; k < e.arity(); ++k) {
02480       if(d_realType != getBaseType(e[k]))
02481         throw TypecheckException("Expecting type REAL with `" +
02482                                  getEM()->getKindName(e.getKind()) + "',\n"+
02483                                  "but got a " + getBaseType(e[k]).toString()+ 
02484                                  " for:\n" + e.toString());
02485       if(isInt && !isInteger(e[k]))
02486         isInt = false;
02487     }
02488     if(isInt)
02489       e.setType(d_intType);
02490     else
02491       e.setType(d_realType);
02492     break;
02493     }
02494   case DIVIDE: {
02495     Expr numerator = e[0];
02496     Expr denominator = e[1];
02497     if (getBaseType(numerator) != d_realType ||
02498         getBaseType(denominator) != d_realType) {
02499       throw TypecheckException("Expecting only REAL types with `DIVIDE',\n"
02500                                "but got " + getBaseType(numerator).toString()+ 
02501                                " and " + getBaseType(denominator).toString() +
02502                                " for:\n" + e.toString());
02503     }
02504     if(denominator.isRational() && 1 == denominator.getRational())
02505       e.setType(numerator.getType());
02506     else
02507       e.setType(d_realType);
02508     break;
02509     }
02510   case LT:
02511   case LE:
02512   case GT:
02513   case GE:
02514   case GRAY_SHADOW:
02515     // Need to know types for all exprs -Clark
02516     //    e.setType(boolType());
02517     //    break;
02518   case DARK_SHADOW:
02519     for (int k = 0; k < e.arity(); ++k) {
02520       if (d_realType != getBaseType(e[k]))
02521         throw TypecheckException("Expecting type REAL with `" +
02522                                  getEM()->getKindName(e.getKind()) + "',\n"+
02523                                  "but got a " + getBaseType(e[k]).toString()+ 
02524                                  " for:\n" + e.toString());
02525     }
02526 
02527     e.setType(boolType());
02528     break;
02529   case IS_INTEGER:
02530     if(d_realType != getBaseType(e[0]))
02531       throw TypecheckException("Expected type REAL, but got "
02532                                +getBaseType(e[0]).toString()
02533                                +"\n\nExpr = "+e.toString());
02534     e.setType(boolType());
02535     break;
02536   default:
02537     DebugAssert(false,"TheoryArith::computeType: unexpected expression:\n "
02538                 +e.toString());
02539     break;
02540   }
02541 }
02542 
02543 
02544 Type TheoryArith::computeBaseType(const Type& t) {
02545   IF_DEBUG(int kind = t.getExpr().getKind());
02546   DebugAssert(kind==INT || kind==REAL || kind==SUBRANGE,
02547               "TheoryArith::computeBaseType("+t.toString()+")");
02548   return realType();
02549 }
02550 
02551 
02552 Expr
02553 TheoryArith::computeTCC(const Expr& e) {
02554   Expr tcc(Theory::computeTCC(e));
02555   switch(e.getKind()) {
02556   case DIVIDE:
02557     DebugAssert(e.arity() == 2, "");
02558     return tcc.andExpr(!(e[1].eqExpr(rat(0))));
02559   default:
02560     return tcc;
02561   }
02562 }
02563 
02564 ///////////////////////////////////////////////////////////////////////////////
02565 //parseExprOp:
02566 //translating special Exprs to regular EXPR??
02567 ///////////////////////////////////////////////////////////////////////////////
02568 Expr
02569 TheoryArith::parseExprOp(const Expr& e) {
02570   TRACE("parser", "TheoryArith::parseExprOp(", e, ")");
02571   //std::cout << "Were here";
02572   // If the expression is not a list, it must have been already
02573   // parsed, so just return it as is.
02574   switch(e.getKind()) {
02575   case ID: {
02576     int kind = getEM()->getKind(e[0].getString());
02577     switch(kind) {
02578     case NULL_KIND: return e; // nothing to do
02579     case REAL:
02580     case INT:
02581     case NEGINF: 
02582     case POSINF: return getEM()->newLeafExpr(kind);
02583     default:
02584       DebugAssert(false, "Bad use of bare keyword: "+e.toString());
02585       return e;
02586     }
02587   }
02588   case RAW_LIST: break; // break out of switch, do the hard work
02589   default:
02590     return e;
02591   }
02592 
02593   DebugAssert(e.getKind() == RAW_LIST && e.arity() > 0,
02594               "TheoryArith::parseExprOp:\n e = "+e.toString());
02595   
02596   const Expr& c1 = e[0][0];
02597   int kind = getEM()->getKind(c1.getString());
02598   switch(kind) {
02599     case UMINUS: {
02600       if(e.arity() != 2)
02601         throw ParserException("UMINUS requires exactly one argument: "
02602                         +e.toString());
02603       return uminusExpr(parseExpr(e[1])); 
02604     }
02605     case PLUS: {
02606       vector<Expr> k;
02607       Expr::iterator i = e.begin(), iend=e.end();
02608       // Skip first element of the vector of kids in 'e'.
02609       // The first element is the operator.
02610       ++i; 
02611       // Parse the kids of e and push them into the vector 'k'
02612       for(; i!=iend; ++i) k.push_back(parseExpr(*i));
02613       return plusExpr(k); 
02614     }
02615     case MINUS: {
02616       if(e.arity() == 2)
02617         return uminusExpr(parseExpr(e[1]));
02618       else if(e.arity() == 3)
02619         return minusExpr(parseExpr(e[1]), parseExpr(e[2]));
02620       else
02621         throw ParserException("MINUS requires one or two arguments:"
02622                         +e.toString());
02623     }
02624     case MULT: {
02625       vector<Expr> k;
02626       Expr::iterator i = e.begin(), iend=e.end();
02627       // Skip first element of the vector of kids in 'e'.
02628       // The first element is the operator.
02629       ++i; 
02630       // Parse the kids of e and push them into the vector 'k'
02631       for(; i!=iend; ++i) k.push_back(parseExpr(*i));
02632       return multExpr(k);
02633     }
02634     case POW: { 
02635       return powExpr(parseExpr(e[1]), parseExpr(e[2])); 
02636     }
02637     case DIVIDE:
02638       { return divideExpr(parseExpr(e[1]), parseExpr(e[2]));    }
02639     case LT:    
02640       { return ltExpr(parseExpr(e[1]), parseExpr(e[2]));        }
02641     case LE:    
02642       { return leExpr(parseExpr(e[1]), parseExpr(e[2]));        }
02643     case GT:    
02644       { return gtExpr(parseExpr(e[1]), parseExpr(e[2]));        }
02645     case GE:    
02646       { return geExpr(parseExpr(e[1]), parseExpr(e[2]));        }
02647     case INTDIV:
02648     case MOD:
02649     case SUBRANGE: {
02650       vector<Expr> k;
02651       Expr::iterator i = e.begin(), iend=e.end();
02652       // Skip first element of the vector of kids in 'e'.
02653       // The first element is the operator.
02654       ++i; 
02655       // Parse the kids of e and push them into the vector 'k'
02656       for(; i!=iend; ++i) 
02657         k.push_back(parseExpr(*i));
02658       return Expr(kind, k, e.getEM());
02659     }
02660     case IS_INTEGER: {
02661       if(e.arity() != 2)
02662         throw ParserException("IS_INTEGER requires exactly one argument: "
02663                         +e.toString());
02664       return Expr(IS_INTEGER, parseExpr(e[1]));
02665     }
02666     default:
02667       DebugAssert(false,
02668                   "TheoryArith::parseExprOp: invalid input " + e.toString());
02669       break;
02670   }
02671   return e;
02672 }
02673 
02674 ///////////////////////////////////////////////////////////////////////////////
02675 // Pretty-printing                                                           //
02676 ///////////////////////////////////////////////////////////////////////////////
02677 
02678 
02679 // The following 4 functions are helpers for the SMT-LIB output language.
02680 
02681 bool TheoryArith::isSyntacticRational(const Expr& e, Rational& r)
02682 {
02683   if (e.isRational()) {
02684     r = e.getRational();
02685     return true;
02686   }
02687   else if (isUMinus(e)) {
02688     if (isSyntacticRational(e[0], r)) {
02689       r = -r;
02690       return true;
02691     }
02692   }
02693   else if (isDivide(e)) {
02694     Rational num;
02695     if (isSyntacticRational(e[0], num)) {
02696       Rational den;
02697       if (isSyntacticRational(e[1], den)) {
02698         if (den != 0) {
02699           r = num / den;
02700           return true;
02701         }
02702       }
02703     }
02704   }
02705   return false;
02706 }
02707 
02708 
02709 void TheoryArith::printRational(ExprStream& os, const Expr& parent, const Expr& e, const Rational& r, bool checkLhs)
02710 {
02711   if (checkLhs) {
02712     if (parent.isEq() && parent[0] == e) {
02713       // If constant is on lhs, switch sides
02714       if (isMinus(parent[1])) {
02715         printMinus(os, parent, parent[1]);
02716         return;
02717       }
02718       else if (isPlus(parent[1])) {
02719         printPlus(os, parent, parent[1]);
02720         return;
02721       }
02722     }
02723   }
02724 
02725   // Print rational
02726   if (r.isInteger()) {
02727     d_intConstUsed = true;
02728     if (r < 0) {
02729       os << "(" << push << "~" << space << (-r).toString() << push << ")";
02730     }
02731     else os << r.toString();
02732   }
02733   else {
02734     d_realUsed = true;
02735     os << "(" << push << "/ ";
02736     Rational tmp = r.getNumerator();
02737     if (tmp < 0) {
02738       os << "(" << push << "~" << space << (-tmp).toString() << push << ")";
02739     }
02740     else os << tmp.toString();
02741     os << space;
02742     tmp = r.getDenominator();
02743     DebugAssert(tmp > 0 && tmp.isInteger(), "Unexpected rational denominator");
02744     os << tmp.toString() << push << ")";
02745   }
02746 
02747   // Figure out language
02748   if (parent.isNull() || (!parent.isEq() && !isIneq(parent))) {
02749     if (d_langUsed == NOT_USED) d_langUsed = TERMS_ONLY;
02750     return;
02751   }
02752   if (d_langUsed == NONLINEAR) return;
02753   else {
02754     Expr otherSide = parent[0];
02755     if (otherSide == e) otherSide = parent[1];
02756     if (isPlus(otherSide) || isMinus(otherSide))
02757       return;
02758   }
02759   if (d_convertToDiff == "" || parent.isEq()) d_langUsed = LINEAR;
02760 }
02761 
02762 
02763 bool TheoryArith::isSyntacticUMinusVar(const Expr& e, Expr& var)
02764 {
02765   if (isUMinus(e)) {
02766     if (isLeaf(e[0])) {
02767       var = e[0];
02768       return true;
02769     }
02770   }
02771   else if (isMult(e)) {
02772     Expr coeff;
02773     if (isLeaf(e[0])) {
02774       var = e[0];
02775       coeff = e[1];
02776     }
02777     else if (isLeaf(e[1])) {
02778       var = e[1];
02779       coeff = e[0];
02780     }
02781     else return false;
02782     if (coeff.isRational() && coeff.getRational() == -1) {
02783       return true;
02784     }
02785     else if (isUMinus(coeff) && coeff[0].isRational() &&
02786              coeff[0].getRational() == 1) {
02787       return true;
02788     }
02789   }
02790   return false;
02791 }
02792 
02793 
02794 void TheoryArith::printPlus(ExprStream& os, const Expr& parent, const Expr& e)
02795 {
02796   int i=0, iend=e.arity();
02797   bool diff = false;
02798   Expr var;
02799 
02800   // Write as DIFF if possible
02801   if (iend == 2 && isLeaf(e[0]) && isSyntacticUMinusVar(e[1], var)) {
02802     os << "(" << push << "-" << space << e[0]
02803        << space << var << push << ")";
02804     diff = true;
02805   }
02806   else if (iend == 2 && isLeaf(e[1]) && isSyntacticUMinusVar(e[0], var)) {
02807     os << "(" << push << "-" << space << e[1]
02808        << space << var << push << ")";
02809     diff = true;;
02810   }
02811   else {
02812     for(; i!=iend; ++i) {
02813       if (i < iend-1) {
02814         if (i > 0) os << space;
02815         os << "(" << push << "+";
02816       }
02817       os << space << e[i];
02818     }
02819     for (i=0; i < iend-1; ++i) os << push << ")";
02820   }
02821 
02822   // Figure out language
02823   if (parent.isNull() || (!parent.isEq() && !isIneq(parent))) {
02824     if (d_langUsed == NOT_USED) d_langUsed = TERMS_ONLY;
02825     return;
02826   }
02827   if (d_langUsed >= LINEAR) return;
02828   else if (diff) {
02829     Expr otherSide = parent[0];
02830     Rational r;
02831     if (otherSide == e) otherSide = parent[1];
02832     if (isSyntacticRational(otherSide, r)) {
02833       d_langUsed = DIFF_ONLY;
02834       return;
02835     }
02836   }
02837   d_langUsed = LINEAR;
02838 }
02839 
02840 
02841 void TheoryArith::printMinus(ExprStream& os, const Expr& parent, const Expr& e)
02842 {
02843   os << "(" << push << "- " << e[0] << space << e[1] << push << ")";
02844   // Figure out language
02845   if (parent.isNull() || (!parent.isEq() && !isIneq(parent))) {
02846     if (d_langUsed == NOT_USED) d_langUsed = TERMS_ONLY;
02847     return;
02848   }
02849   if (d_langUsed >= LINEAR) return;
02850   else if (isLeaf(e[0]) && isLeaf(e[1])) {
02851     Expr otherSide = parent[0];
02852     Rational r;
02853     if (otherSide == e) otherSide = parent[1];
02854     if (isSyntacticRational(otherSide, r)) {
02855       d_langUsed = DIFF_ONLY;
02856       return;
02857     }
02858   }
02859   d_langUsed = LINEAR;
02860 }
02861 
02862 
02863 void TheoryArith::printLhs(ExprStream& os, const Expr& e)
02864 {
02865   if (d_convertToDiff != "") {
02866     switch (e.getKind()) {
02867       case RATIONAL_EXPR:
02868       case SUBRANGE:
02869       case IS_INTEGER:
02870       case PLUS:
02871       case MINUS:
02872       case UMINUS:
02873       case MULT:
02874       case POW:
02875       case DIVIDE:
02876       case DARK_SHADOW:
02877       case GRAY_SHADOW:
02878         break;
02879       case CONSTDEF:
02880         if (e.arity() == 2) {
02881           printLhs(os, e[1]);
02882           return;
02883         }
02884         //fall through
02885       default:
02886         os << "(" << push << "-" << space
02887            << e << space << d_zeroVar << push << ")";
02888         return;
02889     }
02890   }
02891   os << e;
02892 }
02893 
02894 
02895 Expr TheoryArith::rewriteToDiff(const Expr& e)
02896 {
02897   Expr tmp = e[0] - e[1];
02898   tmp = canonRec(tmp).getRHS();
02899   switch (tmp.getKind()) {
02900     case RATIONAL_EXPR: {
02901       Rational r = tmp.getRational();
02902       switch (e.getKind()) {
02903         case LT:
02904           if (r < 0) return trueExpr();
02905           else return falseExpr();
02906         case LE:
02907           if (r <= 0) return trueExpr();
02908           else return falseExpr();
02909         case GT:
02910           if (r > 0) return trueExpr();
02911           else return falseExpr();
02912         case GE:
02913           if (r >= 0) return trueExpr();
02914           else return falseExpr();
02915         case EQ:
02916           if (r == 0) return trueExpr();
02917           else return falseExpr();
02918       }
02919     }
02920     case MULT:
02921       if (d_convertToDiff == "") return e;
02922       DebugAssert(tmp[0].isRational(), "Unexpected term structure from canon");
02923       if (tmp[0].getRational() != -1) return e;
02924       return Expr(e.getOp(), d_zeroVar - tmp[1], rat(0));
02925     case PLUS: {
02926       Expr c = tmp[0];
02927       DebugAssert(c.isRational(), "Unexpected term structure from canon");
02928       Expr x, y;
02929       if (tmp.arity() == 2) {
02930         if (tmp[1].getKind() == MULT) {
02931           x = d_zeroVar;
02932           y = tmp[1];
02933         }
02934         else {
02935           x = tmp[1];
02936           y = rat(-1) * d_zeroVar;
02937         }
02938       }
02939       else if (tmp.arity() == 3) {
02940         if (tmp[1].getKind() == MULT) {
02941           x = tmp[2];
02942           y = tmp[1];
02943         }
02944         else if (tmp[2].getKind() == MULT) {
02945           x = tmp[1];
02946           y = tmp[2];
02947         }
02948         else return e;
02949       }
02950       else return e;
02951       if (x.getKind() == MULT) return e;
02952       DebugAssert(y[0].isRational(), "Unexpected term structure from canon");
02953       if (y[0].getRational() != -1) return e;
02954       return Expr(e.getOp(), x - y[1], -c);
02955     }
02956     default:
02957       if (d_convertToDiff != "") {
02958         return Expr(e.getOp(), tmp - d_zeroVar, rat(0));
02959       }
02960       break;
02961   }
02962   return e;
02963 }
02964 
02965 
02966 bool TheoryArith::isAtomicArithTerm(const Expr& e)
02967 {
02968   switch (e.getKind()) {
02969     case RATIONAL_EXPR:
02970       return true;
02971     case ITE:
02972       return false;
02973     case UMINUS:
02974     case PLUS:
02975     case MINUS:
02976     case MULT:
02977     case DIVIDE:
02978     case POW:
02979     case INTDIV:
02980     case MOD: {
02981       int i=0, iend=e.arity();
02982       for(; i!=iend; ++i) {
02983         if (!isAtomicArithTerm(e[i])) return false;
02984       }
02985       break;
02986     }
02987     default:
02988       break;
02989   }
02990   return true;
02991 }
02992 
02993 
02994 bool TheoryArith::isAtomicArithFormula(const Expr& e)
02995 {
02996   switch (e.getKind()) {
02997     case LT:
02998     case GT:
02999     case LE:
03000     case GE:
03001     case EQ:
03002       return isAtomicArithTerm(e[0]) && isAtomicArithTerm(e[1]);
03003   }
03004   return false;
03005 }
03006 
03007 
03008 ExprStream&
03009 TheoryArith::print(ExprStream& os, const Expr& e) {
03010   switch(os.lang()) {
03011     case PRESENTATION_LANG:
03012       switch(e.getKind()) {
03013         case REAL:
03014         case INT:
03015         case RATIONAL_EXPR:
03016         case NEGINF:
03017         case POSINF:
03018           e.print(os);
03019           break;
03020         case SUBRANGE:
03021           if(e.arity() != 2) e.printAST(os);
03022           else 
03023             os << "[" << push << e[0] << ".." << e[1] << push << "]";
03024           break;
03025         case IS_INTEGER:
03026           if(e.arity() == 1)
03027             os << "IS_INTEGER(" << push << e[0] << push << ")";
03028           else
03029             e.printAST(os);
03030           break;
03031         case PLUS:  {
03032           int i=0, iend=e.arity();
03033           os << "(" << push;
03034           if(i!=iend) os << e[i];
03035           ++i;
03036           for(; i!=iend; ++i) os << space << "+ " << e[i];
03037           os << push << ")";
03038           break;
03039         }
03040         case MINUS:
03041           os << "(" << push << e[0] << space << "- " << e[1] << push << ")";
03042           break;
03043         case UMINUS:
03044           os << "-(" << push << e[0] << push << ")";
03045           break;
03046         case MULT:  {
03047           int i=0, iend=e.arity();
03048           os << "(" << push;
03049           if(i!=iend) os << e[i];
03050           ++i;
03051           for(; i!=iend; ++i) os << space << "* " << e[i];
03052           os << push << ")";
03053           break;
03054         }
03055         case POW:
03056           os << "(" << push << e[1] << space << "^ " << e[0] << push << ")";
03057           break;
03058         case DIVIDE:
03059           os << "(" << push << e[0] << space << "/ " << e[1] << push << ")";
03060           break;
03061         case LT:
03062           if (isInt(e[0].getType()) || isInt(e[1].getType())) {
03063           }
03064           os << "(" << push << e[0] << space << "< " << e[1] << push << ")";
03065           break;
03066         case LE:
03067           os << "(" << push << e[0] << space << "<= " << e[1] << push << ")";
03068           break;
03069         case GT:
03070           os << "(" << push << e[0] << space << "> " << e[1] << push << ")";
03071           break;
03072         case GE:
03073           os << "(" << push << e[0] << space << ">= " << e[1] << push << ")";
03074           break;
03075         case DARK_SHADOW:
03076           os << "DARK_SHADOW(" << push << e[0] << ", " << space << e[1] << push << ")";
03077           break;
03078         case GRAY_SHADOW:
03079           os << "GRAY_SHADOW(" << push << e[0] << ","  << space << e[1]
03080              << "," << space << e[2] << "," << space << e[3] << push << ")";
03081           break;
03082         default:
03083           // Print the top node in the default LISP format, continue with
03084           // pretty-printing for children.
03085           e.printAST(os);
03086 
03087           break;
03088       } 
03089       break; // end of case PRESENTATION_LANG
03090     case SMTLIB_LANG: {
03091       Expr parent = os.getParent();
03092       switch(e.getKind()) {
03093         case RATIONAL_EXPR:
03094           printRational(os, parent, e, e.getRational());
03095           break;
03096         case REAL:
03097           if(theoryCore()->getFlags()["real2int"].getBool()) {
03098             d_intUsed = true;
03099             os << "Int";
03100           }
03101           else {
03102             d_realUsed = true;
03103             os << "Real";
03104           }
03105           break;
03106         case INT:
03107           d_intUsed = true;
03108           os << "Int";
03109           break;
03110         case SUBRANGE:
03111           throw SmtlibException("TheoryArith::print: SMTLIB: SUBRANGE not implemented");
03112 //           if(e.arity() != 2) e.print(os);
03113 //           else 
03114 //             os << "(" << push << "SUBRANGE" << space << e[0]
03115 //             << space << e[1] << push << ")";
03116           break;
03117         case IS_INTEGER:
03118           d_intUsed = true;
03119           if(e.arity() == 1)
03120             os << "(" << push << "IsInt" << space << e[0] << push << ")";
03121           else
03122             throw SmtlibException("TheoryArith::print: SMTLIB: IS_INTEGER used unexpectedly");
03123           break;
03124         case PLUS:  {
03125           Rational r;
03126           if (parent.isEq() && isSyntacticRational(parent[0], r)) {
03127             printRational(os, parent, parent[0], r, false);
03128           }
03129           else {
03130             printPlus(os, parent, e);
03131           }
03132           break;
03133         }
03134         case MINUS: {
03135           Rational r;
03136           if (parent.isEq() && isSyntacticRational(parent[0], r)) {
03137             printRational(os, parent, parent[0], r, false);
03138           }
03139           else {
03140             printMinus(os, parent, e);
03141           }
03142           break;
03143         }
03144         case UMINUS: {
03145           Rational r;
03146           if (isSyntacticRational(e, r)) {
03147             printRational(os, parent, e, r);
03148           }
03149           else {
03150             os << "(" << push << "~" << space << e[0] << push << ")";
03151             if (parent.isNull() || (!parent.isEq() && !isIneq(parent))) {
03152               if (d_langUsed == NOT_USED) d_langUsed = TERMS_ONLY;
03153               break;
03154             }
03155             if (d_langUsed >= LINEAR) break;
03156             d_langUsed = LINEAR;
03157           }
03158           break;
03159         }
03160         case MULT:  {
03161           int i=0, iend=e.arity();
03162           for(; i!=iend; ++i) {
03163             if (i < iend-1) {
03164               os << "(" << push << "*";
03165             }
03166             os << space << e[i];
03167           }
03168           for (i=0; i < iend-1; ++i) os << push << ")";
03169           // Figure out language
03170           if (parent.isNull() || (!parent.isEq() && !isIneq(parent))) {
03171             if (d_langUsed == NOT_USED) d_langUsed = TERMS_ONLY;
03172             break;
03173           }
03174           if (d_langUsed == NONLINEAR) break;
03175           d_langUsed = LINEAR;
03176           bool nonconst = false;
03177           Rational r;
03178           for (i=0; i!=iend; ++i) {
03179             if (isSyntacticRational(e[i], r)) {
03180               continue;
03181             }
03182             if (nonconst) {
03183               d_langUsed = NONLINEAR;
03184               break;
03185             }
03186             nonconst = true;
03187           }
03188           break;
03189         }
03190         case POW:
03191           throw SmtlibException("TheoryArith::print: SMTLIB: POW not supported");
03192           os << "(" << push << "^ " << e[1] << space << e[0] << push << ")";
03193           break;
03194         case DIVIDE: {
03195           Rational r;
03196           if (isSyntacticRational(e, r)) {
03197             printRational(os, parent, e, r);
03198             break;
03199           }
03200           else if (e[1].isRational()) {
03201             r = e[1].getRational();
03202             if (r != 0) {
03203               r = 1 / r;
03204               os << "(" << push << "*" << space << e[0] << space;
03205               printRational(os, Expr(), Expr(), r, false);
03206               os << push << ")";
03207               // Figure out language
03208               if (parent.isNull() || (!parent.isEq() && !isIneq(parent))) {
03209                 if (d_langUsed == NOT_USED) d_langUsed = TERMS_ONLY;
03210                 break;
03211               }
03212               if (d_langUsed == NONLINEAR) break;
03213               d_langUsed = LINEAR;
03214               break;
03215             }
03216           }
03217           throw SmtlibException("TheoryArith::print: SMTLIB: unexpected use of DIVIDE");
03218           break;
03219         }
03220         case LT: {
03221           Rational r;
03222           if (isSyntacticRational(e[0], r)) {
03223             os << "(" << push << ">" << space;
03224             printLhs(os, e[1]);
03225             os << space << e[0] << push << ")";
03226           }
03227           else {
03228             os << "(" << push << "<" << space;
03229             printLhs(os, e[0]);
03230             os << space << e[1] << push << ")";
03231           }
03232           if (d_langUsed >= DIFF_ONLY) break;
03233           if (!isAtomicArithFormula(e)) d_langUsed = LINEAR;
03234           else d_langUsed = DIFF_ONLY;
03235           break;
03236         }
03237         case LE: {
03238           Rational r;
03239           if (isSyntacticRational(e[0], r)) {
03240             os << "(" << push << ">=" << space;
03241             printLhs(os, e[1]);
03242             os << space << e[0] << push << ")";
03243           }
03244           else {
03245             os << "(" << push << "<=" << space;
03246             printLhs(os, e[0]);
03247             os << space << e[1] << push << ")";
03248           }
03249           if (d_langUsed >= DIFF_ONLY) break;
03250           if (!isAtomicArithFormula(e)) d_langUsed = LINEAR;
03251           else d_langUsed = DIFF_ONLY;
03252           break;
03253         }
03254         case GT: {
03255           Rational r;
03256           if (isSyntacticRational(e[0], r)) {
03257             os << "(" << push << "<" << space;
03258             printLhs(os, e[1]);
03259             os << space << e[0] << push << ")";
03260           }
03261           else {
03262             os << "(" << push << ">" << space;
03263             printLhs(os, e[0]);
03264             os << space << e[1] << push << ")";
03265           }
03266           if (d_langUsed >= DIFF_ONLY) break;
03267           if (!isAtomicArithFormula(e)) d_langUsed = LINEAR;
03268           else d_langUsed = DIFF_ONLY;
03269           break;
03270         }
03271         case GE: {
03272           Rational r;
03273           if (isSyntacticRational(e[0], r)) {
03274             os << "(" << push << "<=" << space;
03275             printLhs(os, e[1]);
03276             os << space << e[0] << push << ")";
03277           }
03278           else {
03279             os << "(" << push << ">=" << space;
03280             printLhs(os, e[0]);
03281             os << space << e[1] << push << ")";
03282           }
03283           if (d_langUsed >= DIFF_ONLY) break;
03284           if (!isAtomicArithFormula(e)) d_langUsed = LINEAR;
03285           else d_langUsed = DIFF_ONLY;
03286           break;
03287         }
03288         case DARK_SHADOW:
03289           throw SmtlibException("TheoryArith::print: SMTLIB: DARK_SHADOW not supported");
03290           os << "(" << push << "DARK_SHADOW" << space << e[0]
03291              << space << e[1] << push << ")";
03292           break;
03293         case GRAY_SHADOW:
03294           throw SmtlibException("TheoryArith::print: SMTLIB: GRAY_SHADOW not supported");
03295           os << "GRAY_SHADOW(" << push << e[0] << ","  << space << e[1]
03296              << "," << space << e[2] << "," << space << e[3] << push << ")";
03297           break;
03298         default:
03299           throw SmtlibException("TheoryArith::print: SMTLIB: default not supported");
03300           // Print the top node in the default LISP format, continue with
03301           // pretty-printing for children.
03302           e.printAST(os);
03303 
03304           break;
03305       } 
03306       break; // end of case SMTLIB_LANG
03307     }
03308     case LISP_LANG:
03309       switch(e.getKind()) {
03310         case REAL:
03311         case INT:
03312         case RATIONAL_EXPR:
03313         case NEGINF:
03314         case POSINF:
03315           e.print(os);
03316           break;
03317         case SUBRANGE:
03318           if(e.arity() != 2) e.printAST(os);
03319           else 
03320             os << "(" << push << "SUBRANGE" << space << e[0]
03321                << space << e[1] << push << ")";
03322           break;
03323         case IS_INTEGER:
03324           if(e.arity() == 1)
03325             os << "(" << push << "IS_INTEGER" << space << e[0] << push << ")";
03326           else
03327             e.printAST(os);
03328           break;
03329         case PLUS:  {
03330           int i=0, iend=e.arity();
03331           os << "(" << push << "+";
03332           for(; i!=iend; ++i) os << space << e[i];
03333           os << push << ")";
03334           break;
03335         }
03336         case MINUS:
03337         //os << "(" << push << e[0] << space << "- " << e[1] << push << ")";
03338           os << "(" << push << "- " << e[0] << space << e[1] << push << ")";
03339           break;
03340         case UMINUS:
03341           os << "(" << push << "-" << space << e[0] << push << ")";
03342           break;
03343         case MULT:  {
03344           int i=0, iend=e.arity();
03345           os << "(" << push << "*";
03346           for(; i!=iend; ++i) os << space << e[i];
03347           os << push << ")";
03348           break;
03349         }
03350         case POW:
03351           os << "(" << push << "^ " << e[1] << space << e[0] << push << ")";
03352           break;
03353         case DIVIDE:
03354           os << "(" << push << "/ " << e[0] << space << e[1] << push << ")";
03355           break;
03356         case LT:
03357           os << "(" << push << "< " << e[0] << space << e[1] << push << ")";
03358           break;
03359         case LE:
03360           os << "(" << push << "<= " << e[0] << space << e[1] << push << ")";
03361           break;
03362         case GT:
03363           os << "(" << push << "> " << e[1]  << space << e[0] << push << ")";
03364           break;
03365         case GE:
03366           os << "(" << push << ">= " << e[0] << space << e[1] << push << ")";
03367           break;
03368         case DARK_SHADOW:
03369           os << "(" << push << "DARK_SHADOW" << space << e[0]
03370              << space << e[1] << push << ")";
03371           break;
03372         case GRAY_SHADOW:
03373           os << "(" << push << "GRAY_SHADOW" << space << e[0] << space
03374              << e[1] << space << e[2] << space << e[3] << push << ")";
03375           break;
03376         default:
03377           // Print the top node in the default LISP format, continue with
03378           // pretty-printing for children.
03379           e.printAST(os);
03380 
03381           break;
03382       } 
03383       break; // end of case LISP_LANG
03384     default:
03385      // Print the top node in the default LISP format, continue with
03386      // pretty-printing for children.
03387        e.printAST(os);
03388   }
03389   return os;
03390 }
03391 
03392 
03393 //! Construct the gray shadow expression representing c1 <= e <= c2
03394 // Expr TheoryArith::grayShadow(const Expr& v, const Expr& e,
03395 //                           const Rational& c1, const Rational& c2) {
03396 //   ExprGrayShadow ev(getEM(), v, e, c1, c2, d_grayShadowMMIndex);
03397 //   return getEM()->newExpr(&ev);
03398 // }
03399 
03400 
03401 //! Access lhs constant in gray shadow
03402 // const Rational& TheoryArith::getC1(const Expr& e) {
03403 //   DebugAssert(isGrayShadow(e),
03404 //            "TheoryArith::getC1("+e.toString()
03405 //            +"): not a gray shadow");
03406 //   return e.getRatValue(0);
03407 // }
03408 
03409 
03410 //! Access rhs constant in gray shadow
03411 // const Rational& TheoryArith::getC2(const Expr& e) {
03412 //   DebugAssert(isGrayShadow(e),
03413 //            "TheoryArith::getC2("+e.toString()
03414 //            +"): not a gray shadow");
03415 //   return e.getRatValue(1);
03416 // }
03417 
03418 
03419 //! Access the monomial in gray shadow
03420 // const Expr& TheoryArith::getV(const Expr& e) {
03421 //   DebugAssert(isGrayShadow(e),
03422 //            "TheoryArith::getV("+e.toString()
03423 //            +"): not a gray shadow");
03424 //   return e.getExprValue(0);
03425 // }
03426 
03427 //! Access the expression in gray shadow
03428 // const Expr& TheoryArith::getE(const Expr& e) {
03429 //   DebugAssert(isGrayShadow(e),
03430 //            "TheoryArith::getE("+e.toString()
03431 //            +"): not a gray shadow");
03432 //   return e.getExprValue(1);
03433 // }
03434 

Generated on Thu Apr 13 16:57:34 2006 for CVC Lite by  doxygen 1.4.4