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

Generated on Fri May 20 13:13:57 2005 for CVC Lite by  doxygen 1.3.9.1