CVC3

theory_arith_new.cpp

Go to the documentation of this file.
00001 /*****************************************************************************/
00002 /*!
00003  * \file theory_arith_new.cpp
00004  * 
00005  * Author: Dejan Jovanovic
00006  * 
00007  * Created: Thu Jun 14 13:42:00 2007
00008  *
00009  * <hr>
00010  *
00011  * License to use, copy, modify, sell and/or distribute this software
00012  * and its documentation for any purpose is hereby granted without
00013  * royalty, subject to the terms and conditions defined in the \ref
00014  * LICENSE file provided with this distribution.
00015  * 
00016  * <hr>
00017  * 
00018  */
00019 /*****************************************************************************/
00020 
00021 
00022 #include "theory_arith_new.h" 
00023 #include "arith_proof_rules.h"
00024 //#include "arith_expr.h"
00025 #include "arith_exception.h"
00026 #include "typecheck_exception.h"
00027 #include "eval_exception.h"
00028 #include "parser_exception.h"
00029 #include "smtlib_exception.h"
00030 #include "theory_core.h"
00031 #include "command_line_flags.h"
00032 
00033 
00034 using namespace std;
00035 using namespace CVC3;
00036 
00037 
00038 ///////////////////////////////////////////////////////////////////////////////
00039 // TheoryArithNew::FreeConst Methods                                            //
00040 ///////////////////////////////////////////////////////////////////////////////
00041 
00042 namespace CVC3 {
00043 
00044 ostream& operator<<(ostream& os, const TheoryArithNew::FreeConst& fc) {
00045   os << "FreeConst(r=" << fc.getConst() << ", " 
00046      << (fc.strict()? "strict" : "non-strict") << ")";
00047   return os;
00048 }
00049 
00050 ///////////////////////////////////////////////////////////////////////////////
00051 // TheoryArithNew::Ineq Methods                                                 //
00052 ///////////////////////////////////////////////////////////////////////////////
00053 
00054 ostream& operator<<(ostream& os, const TheoryArithNew::Ineq& ineq) {
00055   os << "Ineq(" << ineq.ineq().getExpr() << ", isolated on "
00056      << (ineq.varOnRHS()? "RHS" : "LHS") << ", const = "
00057      << ineq.getConst() << ")";
00058   return os;
00059 }
00060 } // End of namespace CVC3
00061 
00062 
00063 ///////////////////////////////////////////////////////////////////////////////
00064 // TheoryArithNew Private Methods                                               //
00065 ///////////////////////////////////////////////////////////////////////////////
00066 
00067 
00068 Theorem TheoryArithNew::isIntegerThm(const Expr& e) {
00069   // Quick check
00070   if(isReal(e.getType())) return Theorem();
00071   // Try harder
00072   return isIntegerDerive(Expr(IS_INTEGER, e), typePred(e));
00073 }
00074 
00075 
00076 Theorem TheoryArithNew::isIntegerDerive(const Expr& isIntE, const Theorem& thm) {
00077   const Expr& e = thm.getExpr();
00078   // We found it!
00079   if(e == isIntE) return thm;
00080 
00081   Theorem res;
00082   // If the theorem is an AND, look inside each child
00083   if(e.isAnd()) {
00084     int i, iend=e.arity();
00085     for(i=0; i<iend; ++i) {
00086       res = isIntegerDerive(isIntE, getCommonRules()->andElim(thm, i));
00087       if(!res.isNull()) return res;
00088     }
00089   }
00090   return res;
00091 }
00092 
00093 
00094 bool TheoryArithNew::kidsCanonical(const Expr& e) {
00095   if(isLeaf(e)) return true;
00096   bool res(true);
00097   for(int i=0; res && i<e.arity(); ++i) {
00098     Expr simp(canon(e[i]).getRHS());
00099     res = (e[i] == simp);
00100     IF_DEBUG(if(!res) debugger.getOS() << "\ne[" << i << "] = " << e[i]
00101        << "\nsimplified = " << simp << endl;)
00102   }
00103   return res;
00104 }
00105 
00106 
00107 
00108 
00109 /**
00110  * Compute a canonical form for expression e and return a theorem that e is equal to its canonical form.
00111  * Note that canonical form for arith expressions is of the following form:
00112  * 
00113  * b + a_1 x_1 + a_2 x_2 + ... + a_n x_n (ONE SUM EXPRESION)
00114  * 
00115  * or just a rational b (RATIONAL EXPRESSION)
00116  * 
00117  * where a_i and b are rationals and x_i are arithmetical leaves (i.e. variables or non arithmetic terms)
00118  * 
00119  * @author Clark Barrett
00120  * @author Vijay Ganesh
00121  * @since Sat Feb  8 14:46:32 2003
00122  */  
00123 Theorem TheoryArithNew::canon(const Expr& e)
00124 {
00125   // Trace the arith canon of the expression in the debug version
00126   TRACE("arith", "canon(", e , ") {");
00127   
00128   // The invariant is that the kids of the expression should already be canonised 
00129   //DebugAssert(kidsCanonical(e), "TheoryArithNew::canon("+e.toString()+")");
00130   
00131   // The resulting theorem object 
00132     Theorem result;
00133     
00134     switch (e.getKind()) {
00135       
00136       // -E
00137       case UMINUS: {
00138         
00139         // Convert the unary minus to multiplication with -1
00140         result = d_rules->uMinusToMult(e[0]);
00141         
00142         // Get the resulting epression
00143           Expr e2 = result.getRHS();
00144           
00145           // Canonise the resulting expression and combine the theorems
00146           result = transitivityRule(result, canon(e2));
00147       
00148         // UMINUS case break
00149         break;
00150       }
00151       
00152         // e[0] + e[1]
00153       case PLUS: 
00154         
00155         // Call the canonPlus procedure to canonise +
00156         result = d_rules->canonPlus(e);
00157           
00158           // PLUS case break
00159           break;
00160       
00161       // e[0] - e[1]
00162       case MINUS: {
00163           
00164           // Arity of the minus should be exactly 2 (TODO: looks useless, maybe remove)
00165           DebugAssert(e.arity() == 2," ");
00166       
00167           // This produces e[0] + (-1)*e[1], we have to canonize it in 2 steps 
00168           Theorem minus_eq_sum = d_rules->minusToPlus(e[0], e[1]);
00169       
00170           // The resulting sum expression
00171           Expr sum(minus_eq_sum.getRHS());
00172           
00173           // Canonise the sum[1]
00174           Theorem thm(canon(sum[1]));
00175           
00176           // If the sum[1] sayed the same, canonise the sum expression
00177           if(thm.getLHS() == thm.getRHS()) 
00178             result = canonThm(minus_eq_sum);
00179           // The sum changed; do the work
00180           else {
00181             
00182             // Substitute and try to canonise again
00183             Theorem sum_eq_canon = canonThm(substitutivityRule(sum, 1, thm));
00184             
00185             // Combine the results, and thats it
00186             result = transitivityRule(minus_eq_sum, sum_eq_canon);
00187           }
00188           
00189           // MINUS case break 
00190           break;
00191       
00192       }
00193   
00194       // e[0] * e[1]
00195       case MULT:
00196     
00197         // Canonise using the canonMult() proof rule
00198           result = d_rules->canonMult(e);
00199     
00200           // MULT case break
00201           break;
00202   
00203       // e[0] DIV e[1]
00204       case DIVIDE: {
00205   
00206           // Division by 0 is OK (total extension, protected by TCCs)
00207         // if (e[1].isRational() && e[1].getRational() == 0)
00208       // throw ArithException("Divide by 0 error in "+e.toString());
00209           if (e[1].getKind() == PLUS)
00210             throw ArithException("Divide by a PLUS expression not handled in" + e.toString());
00211           
00212           // Canonise the divite using canonDivide() method 
00213           result = d_rules->canonDivide(e);
00214           
00215           // DIVIDE case break
00216           break;  
00217       }
00218     
00219       // e[0]^e[1]
00220       case POW :
00221     
00222         // If we are raising to a constant rational call canonPowConst() proof rule
00223         if(e[1].isRational()) result = d_rules->canonPowConst(e);
00224         // Othervise just return the same expression
00225         else result = reflexivityRule(e);
00226     
00227         // POW case break
00228         break;
00229     
00230       default:
00231         
00232           // How did we get here (TODO: check if need to throw and exception), anyhow, just return the reflexivity rule
00233           result = reflexivityRule(e);
00234      
00235         // Default break 
00236           break;
00237     }
00238   
00239   // Finished with the canonisation, trace the result in the debug version
00240   TRACE("arith","canon => ",result," }");
00241   
00242   // Return the resulting theorem 
00243   return result;
00244 }
00245 
00246 Theorem TheoryArithNew::canonSimplify(const Expr& e) {
00247     // Trace the function on the arith trace flag
00248     TRACE("arith", "canonSimplify(", e, ") {");
00249   
00250     // Assert that all the kids must be already canonical
00251     //DebugAssert(kidsCanonical(e), "TheoryArithNew::canonSimplify("+e.toString()+")");
00252     // Assert that all the leaves must be simplified
00253     //DebugAssert(leavesAreSimp(e), "Expected leaves to be simplified");
00254   
00255     // Make a copy of the expression
00256     Expr tmp(e);
00257   
00258     // Canonise the expresion
00259     Theorem thm = canon(e);
00260     
00261     // If the new simplified expression has a find, use it (TODO: Check whats going on here)
00262     if(thm.getRHS().hasFind())
00263       thm = transitivityRule(thm, find(thm.getRHS()));
00264   
00265     // We shouldn't rely on simplification in this function anymore
00266     DebugAssert(thm.getRHS() == simplifyExpr(thm.getRHS()), "canonSimplify("+e.toString()+")\n"+"canon(e) = "+thm.getRHS().toString()+"\nsimplify(canon(e)) = "+simplifyExpr(thm.getRHS()).toString());
00267 
00268   // Trace the resulting theorem
00269   TRACE("arith", "canonSimplify =>", thm, " }");
00270   
00271   // Return the theorem
00272   return thm;
00273 }
00274 
00275 /*! accepts a theorem, canonizes it, applies iffMP and substituvity to
00276  *  derive the canonized thm
00277  */
00278 Theorem 
00279 TheoryArithNew::canonPred(const Theorem& thm) {
00280   vector<Theorem> thms;
00281   DebugAssert(thm.getExpr().arity() == 2,
00282               "TheoryArithNew::canonPred: bad theorem: "+thm.toString());
00283   Expr e(thm.getExpr());
00284   thms.push_back(canonSimplify(e[0]));
00285   thms.push_back(canonSimplify(e[1]));
00286   return iffMP(thm, substitutivityRule(e.getOp(), thms));
00287 }
00288 
00289 /** 
00290  * Accepts an equivalence theorem, canonizes the subexpressions, applies transitivity and substituvity to derive the canonized theorem.
00291  * 
00292  * @param thm equivalence theorem
00293  * @return the canonised expression theorem
00294  */
00295 Theorem TheoryArithNew::canonPredEquiv(const Theorem& thm) {
00296   
00297   vector<Theorem> thms; // Vector to hold the simplified versions of e[0] and e[1]
00298   
00299   // Arity of the expression should be 2
00300   DebugAssert(thm.getRHS().arity() == 2, "TheoryArithNew::canonPredEquiv: bad theorem: " + thm.toString());
00301   
00302   // Get the expression of the theorem
00303   Expr e(thm.getRHS());
00304   
00305   // Simplify both sides of the equivalence
00306   thms.push_back(canonSimplify(e[0]));
00307   thms.push_back(canonSimplify(e[1]));
00308   
00309   // Return the theorem substituting e[0] and e[1] with their simplified versions
00310   return transitivityRule(thm, substitutivityRule(e.getOp(), thms));
00311 }
00312 
00313 /*! accepts an equivalence theorem whose RHS is a conjunction,
00314  *  canonizes it, applies iffMP and substituvity to derive the
00315  *  canonized thm
00316  */
00317 Theorem
00318 TheoryArithNew::canonConjunctionEquiv(const Theorem& thm) {
00319   vector<Theorem> thms;
00320   return thm;
00321 }
00322 
00323 /*! Pseudo-code for doSolve. (Input is an equation) (output is a Theorem)
00324  *  -# translate e to the form e' = 0
00325  *  -# if (e'.isRational()) then {if e' != 0 return false else true}
00326  *  -# a for loop checks if all the variables are integers. 
00327  *      - if not isolate a suitable real variable and call processRealEq().
00328  *      - if all variables are integers then isolate suitable variable 
00329  *         and call processIntEq(). 
00330  */
00331 Theorem TheoryArithNew::doSolve(const Theorem& thm)
00332 { 
00333   const Expr& e = thm.getExpr();
00334   TRACE("arith eq","doSolve(",e,") {");
00335   DebugAssert(thm.isRewrite(), "thm = "+thm.toString());
00336   Theorem eqnThm;
00337   vector<Theorem> thms;  
00338   // Move LHS to the RHS, if necessary
00339   if(e[0].isRational() && e[0].getRational() == 0)
00340     eqnThm = thm;
00341   else {
00342     eqnThm = iffMP(thm, d_rules->rightMinusLeft(e));
00343     eqnThm = canonPred(eqnThm);
00344   }
00345   // eqnThm is of the form 0 = e'
00346   // 'right' is of the form e'
00347   Expr right = eqnThm.getRHS();
00348   // Check for trivial equation
00349   if (right.isRational()) {
00350     Theorem result = iffMP(eqnThm, d_rules->constPredicate(eqnThm.getExpr()));
00351     TRACE("arith eq","doSolve => ",result," }");
00352     return result;
00353   }
00354 
00355   //normalize
00356   eqnThm = iffMP(eqnThm, normalize(eqnThm.getExpr()));
00357   right = eqnThm.getRHS();
00358   
00359   //eqn is of the form 0 = e' and is normalized where 'right' denotes e'
00360   //FIXME: change processRealEq to accept equations as well instead of theorems
00361   if(!isInteger(right)) {
00362     Theorem res;
00363     try {
00364       res = processRealEq(eqnThm);
00365     } catch(ArithException& e) {
00366       res = symmetryRule(eqnThm); // Flip to e' = 0
00367       TRACE("arith eq", "doSolve: failed to solve an equation: ", e, "");
00368       IF_DEBUG(debugger.counter("FAILED to solve real equalities")++;)
00369       setIncomplete("Non-linear arithmetic inequalities");
00370     }
00371     IF_DEBUG(debugger.counter("solved real equalities")++;)
00372     TRACE("arith eq", "doSolve [real] => ", res, " }");
00373     return res;
00374   }
00375   else {
00376     Theorem res = processIntEq(eqnThm);
00377     IF_DEBUG(debugger.counter("solved int equalities")++;)
00378     TRACE("arith eq", "doSolve [int] => ", res, " }");
00379     return res;
00380   }
00381 }
00382 
00383 /*! pick a monomial for the input equation. This function is used only
00384  *  if the equation is an integer equation. Choose the monomial with
00385  *  the smallest absolute value of coefficient.
00386  */
00387 Expr
00388 TheoryArithNew::pickIntEqMonomial(const Expr& right)
00389 {
00390   DebugAssert(isPlus(right) && right.arity() > 2,
00391               "TheoryArithNew::pickIntEqMonomial right is wrong :-): " +
00392               right.toString());
00393   DebugAssert(right[0].isRational(),
00394               "TheoryArithNew::pickIntEqMonomial. right[0] must be const" +
00395               right.toString());
00396   DebugAssert(isInteger(right),
00397               "TheoryArithNew::pickIntEqMonomial: right is of type int: " +
00398               right.toString());
00399   //right is of the form "C + a1x1 + ... + anxn". min is initialized
00400   //to a1
00401   Expr::iterator i = right.begin();
00402   i++; //skip 'C'
00403   Rational min = isMult(*i) ? abs((*i)[0].getRational()) : 1;
00404   Expr pickedMon = *i;
00405   for(Expr::iterator iend = right.end(); i != iend; ++i) {
00406     Rational coeff = isMult(*i) ? abs((*i)[0].getRational()) : 1;
00407     if(min > coeff) {
00408       min = coeff;
00409       pickedMon = *i;
00410     }
00411   }
00412   return pickedMon;
00413 }
00414 
00415 /*! input is e1=e2<==>0=e' Theorem and some of the vars in e' are of
00416  * type REAL. isolate one of them and send back to framework. output
00417  * is "e1=e2 <==> var = e''" Theorem.
00418  */
00419 Theorem 
00420 TheoryArithNew::processRealEq(const Theorem& eqn)
00421 {
00422   Expr right = eqn.getRHS();
00423   // Find variable to isolate and store it in left.  Pick the largest
00424   // (according to the total ordering) variable.  FIXME: change from
00425   // total ordering to the ordering we devised for inequalities.
00426 
00427   // TODO: I have to pick a variable that appears as a variable in the
00428   // term but does not appear as a variable anywhere else.  The variable
00429   // must appear as a single leaf and not in a MULT expression with some
00430   // other variables and nor in a POW expression.
00431 
00432   bool found = false;
00433   
00434   Expr left;
00435   
00436   if (isPlus(right))  {
00437     for(int i = right.arity()-1; i>=0; --i) {
00438       Expr c = right[i];
00439       if(isRational(c))
00440         continue;
00441       if(!isInteger(c))  {
00442         if (isLeaf(c) || 
00443             ((isMult(c) && c.arity() == 2 && isLeaf(c[1])))) {
00444           int numoccurs = 0;
00445           Expr leaf = isLeaf(c) ? c : c[1];
00446           for (int j = 0; j < right.arity(); ++j) {
00447             if (j!= i
00448     && isLeafIn(leaf, right[j])
00449     // && leaf.subExprOf(right[j])
00450     ) {
00451               numoccurs++;
00452               break;
00453             }
00454           }
00455           if (!numoccurs) {
00456             left = c;
00457             found = true;
00458             break;
00459           }
00460         }
00461       }
00462     }
00463   }
00464   else if ((isMult(right) && right.arity() == 2 && isLeaf(right[1])) ||
00465            isLeaf(right)) {
00466     left = right;
00467     found = true;
00468   }
00469   
00470   if (!found) {
00471     // TODO:
00472     // throw an arithmetic exception that this cannot be done.
00473     throw 
00474       ArithException("Can't find a leaf for solve in "+eqn.toString());
00475   }
00476 
00477   Rational r = -1;
00478   if (isMult(left))  {
00479     DebugAssert(left.arity() == 2, "only leaf should be chosen as lhs");
00480     DebugAssert(left[0].getRational() != 0, "left = "+left.toString());
00481     r = -1/left[0].getRational();
00482     left = left[1];
00483   }
00484 
00485   DebugAssert(isReal(getBaseType(left)) && !isInteger(left),
00486               "TheoryArithNew::ProcessRealEq: left is integer:\n left = "
00487         +left.toString());
00488   // Normalize equation so that coefficient of the monomial
00489   // corresponding to "left" in eqn[1] is -1
00490   Theorem result(iffMP(eqn,
00491            d_rules->multEqn(eqn.getLHS(), eqn.getRHS(), rat(r))));
00492   result = canonPred(result);
00493 
00494   // Isolate left
00495   result = iffMP(result, d_rules->plusPredicate(result.getLHS(),
00496             result.getRHS(), left, EQ));
00497   result = canonPred(result);
00498   TRACE("arith","processRealEq => ",result," }");
00499   return result;
00500 }
00501 
00502 /*!
00503  * \param eqn is a single equation 0 = e
00504  * \return an equivalent Theorem (x = t AND 0 = e'), or just x = t
00505  */
00506 Theorem
00507 TheoryArithNew::processSimpleIntEq(const Theorem& eqn)
00508 {
00509   TRACE("arith eq", "processSimpleIntEq(", eqn.getExpr(), ") {");
00510   DebugAssert(eqn.isRewrite(),
00511               "TheoryArithNew::processSimpleIntEq: eqn must be equality" +
00512               eqn.getExpr().toString());
00513 
00514   Expr right = eqn.getRHS();
00515 
00516   DebugAssert(eqn.getLHS().isRational() && 0 == eqn.getLHS().getRational(),
00517               "TheoryArithNew::processSimpleIntEq: LHS must be 0:\n" +
00518               eqn.getExpr().toString());
00519 
00520   //recall that 0 = c case is already handled in doSolve() function.
00521   if(isMult(right)) {
00522     //here we take care of special case 0=c.x
00523     Expr c,x;
00524     separateMonomial(right, c, x);
00525     Theorem isIntx(isIntegerThm(x));
00526     DebugAssert(!isIntx.isNull(), "right = "+right.toString());
00527     Theorem res(iffMP(eqn, d_rules->intVarEqnConst(eqn.getExpr(), isIntx)));
00528     TRACE("arith eq", "processSimpleIntEq[0 = a*x] => ", res, " }");
00529     return res;
00530   } else if(isPlus(right)) {
00531     if(2 == right.arity()) {
00532       //we take care of special cases like 0 = c + a.x, 0 = c + x,
00533       Expr c,x;
00534       separateMonomial(right[1], c, x);
00535       Theorem isIntx(isIntegerThm(x));
00536       DebugAssert(!isIntx.isNull(), "right = "+right.toString()
00537       +"\n x = "+x.toString());
00538       Theorem res(iffMP(eqn, d_rules->intVarEqnConst(eqn.getExpr(), isIntx)));
00539       TRACE("arith eq", "processSimpleIntEq[0 = c + a*x] => ", res, " }");
00540       return res;
00541     }
00542     DebugAssert(right.arity() > 2,
00543                 "TheoryArithNew::processSimpleIntEq: RHS is not in correct form:"
00544                 +eqn.getExpr().toString());
00545     // Pick a suitable monomial. isolated can be of the form x, a.x, -a.x
00546     Expr isolated = pickIntEqMonomial(right);
00547     TRACE("arith eq", "processSimpleIntEq: isolated = ", isolated, "");
00548 
00549     // First, we compute the 'sign factor' with which to multiply the
00550     // eqn.  if the coeff of isolated is positive (i.e. 'isolated' is
00551     // of the form x or a.x where a>0 ) then r must be -1 and if coeff
00552     // of 'isolated' is negative, r=1.
00553     Rational r = isMult(isolated) ?
00554       ((isolated[0].getRational() > 0) ? -1 : 1) : -1;
00555     Theorem result;
00556     if (-1 == r) {
00557       // r=-1 and hence 'isolated' is 'x' or 'a.x' where a is
00558       // positive.  modify eqn (0=e') to the equation (0=canon(-1*e'))
00559       result = iffMP(eqn, d_rules->multEqn(eqn.getLHS(), right, rat(r)));
00560       result = canonPred(result);
00561       Expr e = result.getRHS();
00562 
00563       // Isolate the 'isolated'
00564       result = iffMP(result,
00565          d_rules->plusPredicate(result.getLHS(),result.getRHS(),
00566               isolated, EQ));
00567     } else {
00568       //r is 1 and hence isolated is -a.x. Make 'isolated' positive.
00569       const Rational& minusa = isolated[0].getRational();
00570       Rational a = -1*minusa;
00571       isolated = (a == 1)? isolated[1] : rat(a) * isolated[1];
00572       
00573       // Isolate the 'isolated'
00574       result = iffMP(eqn, d_rules->plusPredicate(eqn.getLHS(), 
00575              right,isolated,EQ));
00576     }
00577     // Canonize the result
00578     result = canonPred(result);
00579         
00580     //if isolated is 'x' or 1*x, then return result else continue processing.
00581     if(!isMult(isolated) || isolated[0].getRational() == 1) {   
00582       TRACE("arith eq", "processSimpleIntEq[x = rhs] => ", result, " }");
00583       return result;
00584     } else {
00585       DebugAssert(isMult(isolated) && isolated[0].getRational() >= 2,
00586                   "TheoryArithNew::processSimpleIntEq: isolated must be mult "
00587       "with coeff >= 2.\n isolated = " + isolated.toString());
00588 
00589       // Compute IS_INTEGER() for lhs and rhs
00590       Expr lhs = result.getLHS();
00591       Expr rhs = result.getRHS();
00592       Expr a, x;
00593       separateMonomial(lhs, a, x);
00594       Theorem isIntLHS = isIntegerThm(x);
00595       vector<Theorem> isIntRHS;
00596       if(!isPlus(rhs)) { // rhs is a MULT
00597   Expr c, v;
00598   separateMonomial(rhs, c, v);
00599   isIntRHS.push_back(isIntegerThm(v));
00600   DebugAssert(!isIntRHS.back().isNull(), "");
00601       } else { // rhs is a PLUS
00602   DebugAssert(isPlus(rhs), "rhs = "+rhs.toString());
00603   DebugAssert(rhs.arity() >= 2, "rhs = "+rhs.toString());
00604   Expr::iterator i=rhs.begin(), iend=rhs.end();
00605   ++i; // Skip the free constant
00606   for(; i!=iend; ++i) {
00607     Expr c, v;
00608     separateMonomial(*i, c, v);
00609     isIntRHS.push_back(isIntegerThm(v));
00610     DebugAssert(!isIntRHS.back().isNull(), "");
00611   }
00612       }
00613       // Derive (EXISTS (x:INT): x = t2 AND 0 = t3)
00614       result = d_rules->eqElimIntRule(result, isIntLHS, isIntRHS);
00615       // Skolemize the quantifier
00616       result = getCommonRules()->skolemize(result);
00617       // Canonize t2 and t3 generated by this rule
00618       DebugAssert(result.getExpr().isAnd() && result.getExpr().arity() == 2,
00619       "processSimpleIntEq: result = "+result.getExpr().toString());
00620       Theorem thm1 = canonPred(getCommonRules()->andElim(result, 0));
00621       Theorem thm2 = canonPred(getCommonRules()->andElim(result, 1));
00622       Theorem newRes = getCommonRules()->andIntro(thm1, thm2);
00623       if(newRes.getExpr() != result.getExpr()) result = newRes;
00624       
00625       TRACE("arith eq", "processSimpleIntEq => ", result, " }");
00626       return result;
00627     }
00628   } else {
00629     // eqn is 0 = x.  Flip it and return
00630     Theorem result = symmetryRule(eqn);
00631     TRACE("arith eq", "processSimpleIntEq[x = 0] => ", result, " }");
00632     return result;
00633   }
00634 }
00635 
00636 /*! input is e1=e2<==>0=e' Theorem and all of the vars in e' are of
00637  * type INT. isolate one of them and send back to framework. output
00638  * is "e1=e2 <==> var = e''" Theorem and some associated equations in
00639  * solved form.
00640  */
00641 Theorem 
00642 TheoryArithNew::processIntEq(const Theorem& eqn)
00643 {
00644   TRACE("arith eq", "processIntEq(", eqn.getExpr(), ") {");
00645   // Equations in the solved form.  
00646   std::vector<Theorem> solvedAndNewEqs;
00647   Theorem newEq(eqn), result;
00648   bool done(false);
00649   do {
00650     result = processSimpleIntEq(newEq);
00651     // 'result' is of the from (x1=t1)  AND 0=t'
00652     if(result.isRewrite()) {
00653       solvedAndNewEqs.push_back(result);
00654       done = true;
00655     }
00656     else if(!result.getExpr().isFalse()) {
00657       DebugAssert(result.getExpr().isAnd() && result.getExpr().arity() == 2,
00658       "TheoryArithNew::processIntEq("+eqn.getExpr().toString()
00659       +")\n result = "+result.getExpr().toString());
00660       solvedAndNewEqs.push_back(getCommonRules()->andElim(result, 0));
00661       newEq = getCommonRules()->andElim(result, 1);
00662     } else
00663       done = true;
00664   } while(!done);
00665   Theorem res;
00666   if(result.getExpr().isFalse()) res = result;
00667   else res = solvedForm(solvedAndNewEqs);
00668   TRACE("arith eq", "processIntEq => ", res.getExpr(), " }");
00669   return res;
00670 }
00671 
00672 /*!
00673  * Takes a vector of equations and for every equation x_i=t_i
00674  * substitutes t_j for x_j in t_i for all j>i.  This turns the system
00675  * of equations into a solved form.
00676  *
00677  * Assumption: variables x_j may appear in the RHS terms t_i ONLY for
00678  * i<j, but not for i>=j.
00679  */
00680 Theorem
00681 TheoryArithNew::solvedForm(const vector<Theorem>& solvedEqs) 
00682 {
00683   DebugAssert(solvedEqs.size() > 0, "TheoryArithNew::solvedForm()");
00684 
00685   // Trace code
00686   TRACE_MSG("arith eq", "TheoryArithNew::solvedForm:solvedEqs(\n  [");
00687   IF_DEBUG(if(debugger.trace("arith eq")) {
00688     for(vector<Theorem>::const_iterator j = solvedEqs.begin(),
00689     jend=solvedEqs.end(); j!=jend;++j)
00690       TRACE("arith eq", "", j->getExpr(), ",\n   ");
00691   })
00692   TRACE_MSG("arith eq", "  ]) {");
00693   // End of Trace code
00694   
00695   vector<Theorem>::const_reverse_iterator
00696     i = solvedEqs.rbegin(),
00697     iend = solvedEqs.rend();
00698   // Substitution map: a variable 'x' is mapped to a Theorem x=t.
00699   // This map accumulates the resulting solved form.
00700   ExprMap<Theorem> subst;
00701   for(; i!=iend; ++i) {
00702     if(i->isRewrite()) {
00703       Theorem thm = substAndCanonize(*i, subst);
00704       TRACE("arith eq", "solvedForm: subst["+i->getLHS().toString()+"] = ",
00705       thm.getExpr(), "");
00706       subst[i->getLHS()] = thm;
00707     }
00708     else {
00709       // This is the FALSE case: just return the contradiction
00710       DebugAssert(i->getExpr().isFalse(),
00711       "TheoryArithNew::solvedForm: an element of solvedEqs must "
00712       "be either EQ or FALSE: "+i->toString());
00713       return *i;
00714     }
00715   }
00716   // Now we've collected the solved form in 'subst'.  Wrap it up into
00717   // a conjunction and return.
00718   vector<Theorem> thms;
00719   for(ExprMap<Theorem>::iterator i=subst.begin(), iend=subst.end();
00720       i!=iend; ++i)
00721     thms.push_back(i->second);
00722   if (thms.size() > 1)
00723     return getCommonRules()->andIntro(thms);
00724   else
00725     return thms.back();
00726 }
00727 
00728 
00729 /*!
00730  * ASSUMPTION: 't' is a fully canonized arithmetic term, and every
00731  * element of subst is a fully canonized equation of the form x=e,
00732  * indexed by the LHS variable.
00733  */
00734 
00735 Theorem
00736 TheoryArithNew::substAndCanonize(const Expr& t, ExprMap<Theorem>& subst)
00737 {
00738   TRACE("arith eq", "substAndCanonize(", t, ") {");
00739   // Quick and dirty check: return immediately if subst is empty
00740   if(subst.empty()) {
00741     Theorem res(reflexivityRule(t));
00742     TRACE("arith eq", "substAndCanonize[subst empty] => ", res, " }");
00743     return res;
00744   }
00745   // Check if we can substitute 't' directly
00746   ExprMap<Theorem>::iterator i = subst.find(t), iend=subst.end();
00747   if(i!=iend) {
00748     TRACE("arith eq", "substAndCanonize[subst] => ", i->second, " }");
00749     return i->second;
00750   }
00751   // The base case: t is an i-leaf
00752   if(isLeaf(t)) {
00753     Theorem res(reflexivityRule(t));
00754     TRACE("arith eq", "substAndCanonize[i-leaf] => ", res, " }");
00755     return res;
00756   }
00757   // 't' is an arithmetic term; recurse into the children
00758   vector<Theorem> thms;
00759   vector<unsigned> changed;
00760   for(unsigned j=0, jend=t.arity(); j!=jend; ++j) {
00761     Theorem thm = substAndCanonize(t[j], subst);
00762     if(thm.getRHS() != t[j]) {
00763       thm = canonThm(thm);
00764       thms.push_back(thm);
00765       changed.push_back(j);
00766     }
00767   }
00768   // Do the actual substitution and canonize the result
00769   Theorem res;
00770   if(thms.size() > 0) {
00771     res = substitutivityRule(t, changed, thms);
00772     res = canonThm(res);
00773   }
00774   else
00775     res = reflexivityRule(t);
00776   TRACE("arith eq", "substAndCanonize => ", res, " }");
00777   return res;
00778 }
00779 
00780 
00781 /*!
00782  *  ASSUMPTION: 't' is a fully canonized equation of the form x = t,
00783  *  and so is every element of subst, indexed by the LHS variable.
00784  */
00785 
00786 Theorem
00787 TheoryArithNew::substAndCanonize(const Theorem& eq, ExprMap<Theorem>& subst)
00788 {
00789   // Quick and dirty check: return immediately if subst is empty
00790   if(subst.empty()) return eq;
00791 
00792   DebugAssert(eq.isRewrite(), "TheoryArithNew::substAndCanonize: t = "
00793         +eq.getExpr().toString());
00794   const Expr& t = eq.getRHS();
00795   // Do the actual substitution in the term t
00796   Theorem thm = substAndCanonize(t, subst);
00797   // Substitution had no result: return the original equation
00798   if(thm.getRHS() == t) return eq;
00799   // Otherwise substitute the result into the equation
00800   vector<Theorem> thms;
00801   vector<unsigned> changed;
00802   thms.push_back(thm);
00803   changed.push_back(1);
00804   return iffMP(eq, substitutivityRule(eq.getExpr(), changed, thms));
00805 }
00806 
00807 
00808 void TheoryArithNew::updateStats(const Rational& c, const Expr& v)
00809 {
00810   TRACE("arith ineq", "updateStats("+c.toString()+", ", v, ")");
00811   if(c > 0) {
00812     if(d_countRight.count(v) > 0) d_countRight[v] = d_countRight[v] + 1;
00813     else d_countRight[v] = 1;
00814   }
00815   else
00816     if(d_countLeft.count(v) > 0) d_countLeft[v] = d_countLeft[v] + 1;
00817     else d_countLeft[v] = 1;
00818 }
00819 
00820 
00821 void TheoryArithNew::updateStats(const Expr& monomial)
00822 {
00823   Expr c, m;
00824   separateMonomial(monomial, c, m);
00825   updateStats(c.getRational(), m);
00826 }
00827 
00828 
00829 void TheoryArithNew::addToBuffer(const Theorem& thm) {
00830   // First, turn the inequality into 0 < rhs
00831   // FIXME: check if this can be optimized away
00832   Theorem result(thm);
00833   const Expr& e = thm.getExpr();
00834   // int kind = e.getKind();
00835   if(!(e[0].isRational() && e[0].getRational() == 0)) {
00836     result = iffMP(result, d_rules->rightMinusLeft(e));
00837     result = canonPred(result);
00838   }
00839   TRACE("arith ineq", "addToBuffer(", result.getExpr(), ")");
00840   // Push it into the buffer
00841   d_buffer.push_back(thm);
00842 
00843   // Collect the statistics about variables
00844   const Expr& rhs = thm.getExpr()[1];
00845   if(isPlus(rhs))
00846     for(Expr::iterator i=rhs.begin(), iend=rhs.end(); i!=iend; ++i)
00847       updateStats(*i);
00848   else // It's a monomial
00849     updateStats(rhs);
00850 }
00851 
00852 
00853 Expr TheoryArithNew::computeNormalFactor(const Expr& right, NormalizationType type) {
00854     // Strategy: compute f = lcm(d1...dn)/gcd(c1...cn), where the RHS is of the form c1/d1*x1 + ... + cn/dn*xn or a rational
00855   
00856     // The expression must be canonised, i.e. it is a sum or a rational
00857     DebugAssert(isRational(right) || isPlus(right),"TheoryArithNew::computeNormalFactor: " + right.toString() + "wrong kind");
00858   
00859   // The factor we will compute
00860     Rational factor;
00861     
00862     // Sign of the factor 
00863     int sign = 0;
00864     
00865     // In case the expression is a PLUS expression find the gcd
00866     if(isPlus(right)) {
00867       
00868       // Vector of numerators and denominators
00869       vector<Rational> nums, denoms;
00870       
00871       // Pass throught the sum and pick up the integers
00872       for(int i = 0, iend = right.arity(); i < iend; i ++) {
00873       
00874           Rational c(1); // The rational constant of the current summand
00875                 
00876           // If rational or multiplicatino set c to be the apropriate rational
00877           switch(right[i].getKind()) {
00878             
00879             case RATIONAL_EXPR: 
00880             
00881               // Sum term is just a rational, so just add it 
00882               c = abs(right[i].getRational()); 
00883               break;
00884               
00885               case MULT:          
00886                 
00887                 // Sum term is involves multiplication
00888                 c = right[i][0].getRational();
00889                 
00890                 // If this is the first one (sign is still not set) set the sign depending on the sign of the term
00891                 if (!sign) {
00892                   
00893                   // If the normalization type is NORMALIZE_UNIT just return the invese of the first
00894                   if (type == NORMALIZE_UNIT) return rat(1/c);
00895                   
00896                   // Set the sign otherwise
00897                   sign = (c > 0 ? 1 : -1);                  
00898                 }
00899                 
00900                 // Constant should be positive for lcd and gcd computation
00901                 c = abs(c);
00902                 
00903                 break;
00904                 
00905             default: // Stays 1 or everything else
00906               
00907               break;
00908           }
00909           
00910           // Add the demoninator and the numerator to the apropriate vectors
00911           nums.push_back(c.getNumerator());
00912           denoms.push_back(c.getDenominator());   
00913       }
00914     
00915     // Compute the gcd of all the numerators
00916       Rational gcd_nums = gcd(nums);
00917     
00918       // x/0 == 0 in our model, as a total extension of arithmetic.  The
00919       // particular value of x/0 is irrelevant, since the DP is guarded
00920       // by the top-level TCCs, and it is safe to return any value in
00921       // cases when terms are undefined.
00922       factor = (gcd_nums == 0)? 0 : (sign * lcm(denoms) / gcd_nums);
00923     } else 
00924       // The expression is a rational, just return 1
00925       factor = 1;
00926   
00927   // Return the reational expression representing the factor
00928   return rat(factor);
00929 }
00930 
00931 
00932 bool TheoryArithNew::lessThanVar(const Expr& isolatedMonomial, const Expr& var2) 
00933 {
00934   DebugAssert(!isRational(var2) && !isRational(isolatedMonomial),
00935               "TheoryArithNew::findMaxVar: isolatedMonomial cannot be rational" + 
00936               isolatedMonomial.toString());
00937   Expr c, var0, var1;
00938   separateMonomial(isolatedMonomial, c, var0);
00939   separateMonomial(var2, c, var1);
00940   return var0 < var1;
00941 }
00942 
00943 
00944 void TheoryArithNew::separateMonomial(const Expr& e, Expr& c, Expr& var) {
00945   TRACE("separateMonomial", "separateMonomial(", e, ")");
00946   DebugAssert(!isPlus(e), 
00947         "TheoryArithNew::separateMonomial(e = "+e.toString()+")");
00948   if(isMult(e)) {
00949     DebugAssert(e.arity() >= 2,
00950     "TheoryArithNew::separateMonomial(e = "+e.toString()+")");
00951     c = e[0];
00952     if(e.arity() == 2) var = e[1];
00953     else {
00954       vector<Expr> kids = e.getKids();
00955       kids[0] = rat(1);
00956       var = multExpr(kids);
00957     }
00958   } else {
00959     c = rat(1);
00960     var = e;
00961   }
00962   DebugAssert(c.isRational(), "TheoryArithNew::separateMonomial(e = "
00963         +e.toString()+", c = "+c.toString()+")");
00964   DebugAssert(!isMult(var) || (var[0].isRational() && var[0].getRational()==1),
00965         "TheoryArithNew::separateMonomial(e = "
00966         +e.toString()+", var = "+var.toString()+")");
00967 }
00968 
00969 
00970 //returns true if e1 < e2, else false(i.e e2 < e1 or e1,e2 are not
00971 //comparable)
00972 bool TheoryArithNew::VarOrderGraph::lessThan(const Expr& e1, const Expr& e2) 
00973 {
00974   d_cache.clear();
00975   //returns true if e1 is in the subtree rooted at e2 implying e1 < e2
00976   return dfs(e1,e2);
00977 }
00978 
00979 //returns true if e1 is in the subtree rooted at e2 implying e1 < e2
00980 bool TheoryArithNew::VarOrderGraph::dfs(const Expr& e1, const Expr& e2)
00981 {
00982   if(e1 == e2)
00983     return true;
00984   if(d_cache.count(e2) > 0)
00985     return false;
00986   if(d_edges.count(e2) == 0)
00987     return false;
00988   d_cache[e2] = true;
00989   vector<Expr>& e2Edges = d_edges[e2];
00990   vector<Expr>::iterator i = e2Edges.begin();
00991   vector<Expr>::iterator iend = e2Edges.end();
00992   //if dfs finds e1 then i != iend else i is equal to iend
00993   for(; i != iend && !dfs(e1,*i); ++i);
00994   return (i != iend);
00995 }
00996 
00997 
00998 void TheoryArithNew::VarOrderGraph::selectSmallest(vector<Expr>& v1,
00999                                                vector<Expr>& v2) 
01000 {
01001   int v1Size = v1.size();
01002   vector<bool> v3(v1Size);
01003   for(int j=0; j < v1Size; ++j)
01004     v3[j] = false;
01005 
01006   for(int j=0; j < v1Size; ++j) {
01007     if(v3[j]) continue;
01008     for(int i =0; i < v1Size; ++i) {
01009       if((i == j) || v3[i]) 
01010         continue;
01011       if(lessThan(v1[i],v1[j])) {
01012         v3[j] = true;
01013         break;
01014       }
01015     }
01016   }
01017   vector<Expr> new_v1;
01018 
01019   for(int j = 0; j < v1Size; ++j) 
01020     if(!v3[j]) v2.push_back(v1[j]);
01021     else new_v1.push_back(v1[j]);
01022   v1 = new_v1;
01023 }
01024 
01025 
01026 void TheoryArithNew::VarOrderGraph::selectLargest(const vector<Expr>& v1,
01027                                                vector<Expr>& v2) 
01028 {
01029   int v1Size = v1.size();
01030   vector<bool> v3(v1Size);
01031   for(int j=0; j < v1Size; ++j)
01032     v3[j] = false;
01033 
01034   for(int j=0; j < v1Size; ++j) {
01035     if(v3[j]) continue;
01036     for(int i =0; i < v1Size; ++i) {
01037       if((i == j) || v3[i]) 
01038         continue;
01039       if(lessThan(v1[j],v1[i])) {
01040         v3[j] = true;
01041         break;
01042       }
01043     }
01044   }
01045   
01046   for(int j = 0; j < v1Size; ++j) 
01047     if(!v3[j]) v2.push_back(v1[j]);
01048 }
01049 
01050 ///////////////////////////////////////////////////////////////////////////////
01051 // TheoryArithNew Public Methods                                                //
01052 ///////////////////////////////////////////////////////////////////////////////
01053 
01054 
01055 TheoryArithNew::TheoryArithNew(TheoryCore* core)
01056   : TheoryArith(core, "ArithmeticNew"),
01057     d_diseq(core->getCM()->getCurrentContext()),
01058     d_diseqIdx(core->getCM()->getCurrentContext(), 0, 0),
01059     d_inModelCreation(core->getCM()->getCurrentContext(), false, 0),
01060     d_freeConstDB(core->getCM()->getCurrentContext()),
01061     d_buffer(core->getCM()->getCurrentContext()),
01062     // Initialize index to 0 at scope 0
01063     d_bufferIdx(core->getCM()->getCurrentContext(), 0, 0),
01064     d_bufferThres(&(core->getFlags()["ineq-delay"].getInt())),
01065     d_countRight(core->getCM()->getCurrentContext()),
01066     d_countLeft(core->getCM()->getCurrentContext()),
01067     d_sharedTerms(core->getCM()->getCurrentContext()),
01068     d_sharedVars(core->getCM()->getCurrentContext()),
01069     consistent(core->getCM()->getCurrentContext()),
01070     lowerBound(core->getCM()->getCurrentContext()),
01071     upperBound(core->getCM()->getCurrentContext()),
01072     beta(core->getCM()->getCurrentContext()),
01073     assertedExprCount(core->getCM()->getCurrentContext()),
01074     integer_lemma(core->getCM()->getCurrentContext())
01075 {
01076   IF_DEBUG(d_diseq.setName("CDList[TheoryArithNew::d_diseq]");)
01077   IF_DEBUG(d_buffer.setName("CDList[TheoryArithNew::d_buffer]");)
01078   IF_DEBUG(d_bufferIdx.setName("CDList[TheoryArithNew::d_bufferIdx]");)
01079 
01080   getEM()->newKind(REAL, "_REAL", true);
01081   getEM()->newKind(INT, "_INT", true);
01082   getEM()->newKind(SUBRANGE, "_SUBRANGE", true);
01083 
01084   getEM()->newKind(UMINUS, "_UMINUS");
01085   getEM()->newKind(PLUS, "_PLUS");
01086   getEM()->newKind(MINUS, "_MINUS");
01087   getEM()->newKind(MULT, "_MULT");
01088   getEM()->newKind(DIVIDE, "_DIVIDE");
01089   getEM()->newKind(POW, "_POW");
01090   getEM()->newKind(INTDIV, "_INTDIV");
01091   getEM()->newKind(MOD, "_MOD");
01092   getEM()->newKind(LT, "_LT");
01093   getEM()->newKind(LE, "_LE");
01094   getEM()->newKind(GT, "_GT");
01095   getEM()->newKind(GE, "_GE");
01096   getEM()->newKind(IS_INTEGER, "_IS_INTEGER");
01097   getEM()->newKind(NEGINF, "_NEGINF");
01098   getEM()->newKind(POSINF, "_POSINF");
01099   getEM()->newKind(DARK_SHADOW, "_DARK_SHADOW");
01100   getEM()->newKind(GRAY_SHADOW, "_GRAY_SHADOW");
01101 
01102   getEM()->newKind(REAL_CONST, "_REAL_CONST");
01103 
01104   vector<int> kinds;
01105   kinds.push_back(REAL);
01106   kinds.push_back(INT);
01107   kinds.push_back(SUBRANGE);
01108   kinds.push_back(IS_INTEGER);
01109   kinds.push_back(UMINUS);
01110   kinds.push_back(PLUS);
01111   kinds.push_back(MINUS);
01112   kinds.push_back(MULT);
01113   kinds.push_back(DIVIDE);
01114   kinds.push_back(POW);
01115   kinds.push_back(INTDIV);
01116   kinds.push_back(MOD);
01117   kinds.push_back(LT);
01118   kinds.push_back(LE);
01119   kinds.push_back(GT);
01120   kinds.push_back(GE);
01121   kinds.push_back(RATIONAL_EXPR);
01122   kinds.push_back(NEGINF);
01123   kinds.push_back(POSINF);
01124   kinds.push_back(DARK_SHADOW);
01125   kinds.push_back(GRAY_SHADOW);
01126   kinds.push_back(REAL_CONST);
01127 
01128   registerTheory(this, kinds, true);
01129 
01130   d_rules = createProofRules();
01131 
01132   d_realType = Type(getEM()->newLeafExpr(REAL));
01133   d_intType  = Type(getEM()->newLeafExpr(INT));
01134   consistent = SATISFIABLE;
01135   assertedExprCount = 0;
01136 }
01137 
01138 
01139 // Destructor: delete the proof rules class if it's present
01140 TheoryArithNew::~TheoryArithNew() {
01141   if(d_rules != NULL) delete d_rules;
01142   // Clear the inequality databases
01143   for(ExprMap<CDList<Ineq> *>::iterator i=d_inequalitiesRightDB.begin(),
01144   iend=d_inequalitiesRightDB.end(); i!=iend; ++i) {
01145     delete (i->second);
01146     free(i->second);
01147   }
01148   for(ExprMap<CDList<Ineq> *>::iterator i=d_inequalitiesLeftDB.begin(),
01149   iend=d_inequalitiesLeftDB.end(); i!=iend; ++i) {
01150     delete (i->second);
01151     free (i->second);
01152   }
01153 }
01154 
01155 void TheoryArithNew::collectVars(const Expr& e, vector<Expr>& vars,
01156             set<Expr>& cache) {
01157   // Check the cache first
01158   if(cache.count(e) > 0) return;
01159   // Not processed yet.  Cache the expression and proceed
01160   cache.insert(e);
01161   if(isLeaf(e)) vars.push_back(e);
01162   else
01163     for(Expr::iterator i=e.begin(), iend=e.end(); i!=iend; ++i)
01164       collectVars(*i, vars, cache);
01165 }
01166 
01167 void
01168 TheoryArithNew::processFiniteInterval(const Theorem& alphaLEax,
01169            const Theorem& bxLEbeta) {
01170   const Expr& ineq1(alphaLEax.getExpr());
01171   const Expr& ineq2(bxLEbeta.getExpr());
01172   DebugAssert(isLE(ineq1), "TheoryArithNew::processFiniteInterval: ineq1 = "
01173         +ineq1.toString());
01174   DebugAssert(isLE(ineq2), "TheoryArithNew::processFiniteInterval: ineq2 = "
01175         +ineq2.toString());
01176   // If the inequalities are not integer, just return (nothing to do)
01177   if(!isInteger(ineq1[0])
01178      || !isInteger(ineq1[1])
01179      || !isInteger(ineq2[0])
01180      || !isInteger(ineq2[1]))
01181     return;
01182 
01183   const Expr& ax = ineq1[1];
01184   const Expr& bx = ineq2[0];
01185   DebugAssert(!isPlus(ax) && !isRational(ax),
01186         "TheoryArithNew::processFiniteInterval:\n ax = "+ax.toString());
01187   DebugAssert(!isPlus(bx) && !isRational(bx),
01188         "TheoryArithNew::processFiniteInterval:\n bx = "+bx.toString());
01189   Expr a = isMult(ax)? ax[0] : rat(1);
01190   Expr b = isMult(bx)? bx[0] : rat(1);
01191 
01192   Theorem thm1(alphaLEax), thm2(bxLEbeta);
01193   // Multiply the inequalities by 'b' and 'a', and canonize them, if necessary
01194   if(a != b) {
01195     thm1 = canonPred(iffMP(alphaLEax, d_rules->multIneqn(ineq1, b)));
01196     thm2 = canonPred(iffMP(bxLEbeta, d_rules->multIneqn(ineq2, a)));
01197   }
01198   // Check that a*beta - b*alpha == c > 0
01199   const Expr& alphaLEt = thm1.getExpr();
01200   const Expr& alpha = alphaLEt[0];
01201   const Expr& t = alphaLEt[1];
01202   const Expr& beta = thm2.getExpr()[1];
01203   Expr c = canon(beta - alpha).getRHS();
01204 
01205   if(c.isRational() && c.getRational() >= 1) {
01206     // This is a finite interval.  First, derive t <= alpha + c:
01207     // canon(alpha+c) => (alpha+c == beta) ==> [symmetry] beta == alpha+c
01208     // Then substitute that in thm2
01209     Theorem bEQac = symmetryRule(canon(alpha + c));
01210     // Substitute beta == alpha+c for the second child of thm2
01211     vector<unsigned> changed;
01212     vector<Theorem> thms;
01213     changed.push_back(1);
01214     thms.push_back(bEQac);
01215     Theorem tLEac = substitutivityRule(thm2.getExpr(), changed, thms);
01216     tLEac = iffMP(thm2, tLEac);
01217     // Derive and enqueue the finite interval constraint
01218     Theorem isInta(isIntegerThm(alpha));
01219     Theorem isIntt(isIntegerThm(t));
01220     enqueueFact(d_rules->finiteInterval(thm1, tLEac, isInta, isIntt));
01221   }
01222 }
01223 
01224 
01225 void
01226 TheoryArithNew::processFiniteIntervals(const Expr& x) {
01227   // If x is not integer, do not bother
01228   if(!isInteger(x)) return;
01229   // Process every pair of the opposing inequalities for 'x'
01230   ExprMap<CDList<Ineq> *>::iterator iLeft, iRight;
01231   iLeft = d_inequalitiesLeftDB.find(x);
01232   if(iLeft == d_inequalitiesLeftDB.end()) return;
01233   iRight = d_inequalitiesRightDB.find(x);
01234   if(iRight == d_inequalitiesRightDB.end()) return;
01235   // There are some opposing inequalities; get the lists
01236   CDList<Ineq>& ineqsLeft = *(iLeft->second);
01237   CDList<Ineq>& ineqsRight = *(iRight->second);
01238   // Get the sizes of the lists
01239   size_t sizeLeft = ineqsLeft.size();
01240   size_t sizeRight = ineqsRight.size();
01241   // Process all the pairs of the opposing inequalities
01242   for(size_t l=0; l<sizeLeft; ++l)
01243     for(size_t r=0; r<sizeRight; ++r)
01244       processFiniteInterval(ineqsRight[r], ineqsLeft[l]);
01245 }
01246 
01247 /*! This function recursively decends expression tree <strong>without
01248  *  caching</strong> until it hits a node that is already setup.  Be
01249  *  careful on what expressions you are calling it.
01250  */
01251 void
01252 TheoryArithNew::setupRec(const Expr& e) {
01253   if(e.hasFind()) return;
01254   // First, set up the kids recursively
01255   for (int k = 0; k < e.arity(); ++k) {
01256     setupRec(e[k]);
01257   }
01258   // Create a find pointer for e
01259   e.setFind(reflexivityRule(e));
01260   e.setEqNext(reflexivityRule(e));
01261   // And call our own setup()   
01262   setup(e);
01263 }
01264 
01265 
01266 /*!
01267  * Keep track of all finitely bounded integer variables in shared
01268  * terms.
01269  *
01270  * When a new shared term t is reported, all of its variables x1...xn
01271  * are added to the set d_sharedVars.  
01272  *
01273  * For each newly added variable x, check all of its opposing
01274  * inequalities, find out all the finite bounds and assert the
01275  * corresponding GRAY_SHADOW constraints.
01276  *
01277  * When projecting integer inequalities, the database d_sharedVars is
01278  * consulted, and if the variable is in it, check the shadows for
01279  * being a finite interval, and produce the additional GRAY_SHADOW
01280  * constraints.
01281  */
01282 void TheoryArithNew::addSharedTerm(const Expr& e) {
01283   d_sharedTerms[e] = true;
01284   /*
01285   set<Expr> cache; // Aux. cache for collecting i-leaves
01286   vector<Expr> vars; // Vector of vars in e
01287   collectVars(e, vars, cache);
01288   for(vector<Expr>::iterator i=vars.begin(), iend=vars.end(); i!=iend; ++i) {
01289     if(d_sharedVars.count(*i) == 0) {
01290       TRACE("arith shared", "TheoryArithNew::addSharedTerm: new var = ", *i, "");
01291       processFiniteIntervals(*i);
01292       d_sharedVars[*i]=true;
01293     }
01294   }
01295   */
01296 }
01297 
01298 void TheoryArithNew::refineCounterExample()
01299 {
01300   d_inModelCreation = true;
01301   TRACE("model", "refineCounterExample[TheoryArithNew] ", "", "{");
01302   CDMap<Expr, bool>::iterator it = d_sharedTerms.begin(), it2,
01303     iend = d_sharedTerms.end();
01304   // Add equalities over all pairs of shared terms as suggested
01305   // splitters.  Notice, that we want to split on equality
01306   // (positively) first, to reduce the size of the model.
01307   for(; it!=iend; ++it) {
01308     // Copy by value: the elements in the pair from *it are NOT refs in CDMap
01309     Expr e1 = (*it).first;
01310     for(it2 = it, ++it2; it2!=iend; ++it2) {
01311       Expr e2 = (*it2).first;
01312       DebugAssert(isReal(getBaseType(e1)),
01313       "TheoryArithNew::refineCounterExample: e1 = "+e1.toString()
01314       +"\n type(e1) = "+e1.getType().toString());
01315       if(findExpr(e1) != findExpr(e2)) {
01316   DebugAssert(isReal(getBaseType(e2)),
01317         "TheoryArithNew::refineCounterExample: e2 = "+e2.toString()
01318         +"\n type(e2) = "+e2.getType().toString());
01319   Expr eq = simplifyExpr(e1.eqExpr(e2));
01320         if (!eq.isBoolConst())
01321           addSplitter(eq);
01322       }
01323     }
01324   }
01325   TRACE("model", "refineCounterExample[Theory::Arith] ", "", "}");
01326 }
01327 
01328 
01329 void
01330 TheoryArithNew::findRationalBound(const Expr& varSide, const Expr& ratSide, 
01331              const Expr& var,
01332              Rational &r)
01333 {
01334   Expr c, x;
01335   separateMonomial(varSide, c, x);
01336   
01337   DebugAssert(findExpr(c).isRational(), 
01338         "seperateMonomial failed"); 
01339   DebugAssert(findExpr(ratSide).isRational(), 
01340         "smallest variable in graph, should not have variables"
01341         " in inequalities: ");
01342   DebugAssert(x == var, "separateMonomial found different variable: " 
01343         + var.toString());
01344   r = findExpr(ratSide).getRational() / findExpr(c).getRational();
01345 } 
01346 
01347 bool
01348 TheoryArithNew::findBounds(const Expr& e, Rational& lub, Rational&  glb)
01349 {
01350   bool strictLB=false, strictUB=false;
01351   bool right = (d_inequalitiesRightDB.count(e) > 0
01352            && d_inequalitiesRightDB[e]->size() > 0);
01353   bool left = (d_inequalitiesLeftDB.count(e) > 0
01354          && d_inequalitiesLeftDB[e]->size() > 0);
01355   int numRight = 0, numLeft = 0;
01356   if(right) { //rationals less than e
01357     CDList<Ineq> * ratsLTe = d_inequalitiesRightDB[e];
01358     for(unsigned int i=0; i<ratsLTe->size(); i++) {
01359       DebugAssert((*ratsLTe)[i].varOnRHS(), "variable on wrong side!");
01360       Expr ineq = (*ratsLTe)[i].ineq().getExpr();
01361       Expr leftSide = ineq[0], rightSide = ineq[1];
01362       Rational r;
01363       findRationalBound(rightSide, leftSide, e , r);
01364       if(numRight==0 || r>glb){
01365   glb = r;
01366   strictLB = isLT(ineq);
01367       }
01368       numRight++;
01369     }
01370     TRACE("model", "   =>Lower bound ", glb.toString(), "");
01371   }
01372   if(left) {   //rationals greater than e
01373     CDList<Ineq> * ratsGTe = d_inequalitiesLeftDB[e];
01374     for(unsigned int i=0; i<ratsGTe->size(); i++) { 
01375       DebugAssert((*ratsGTe)[i].varOnLHS(), "variable on wrong side!");
01376       Expr ineq = (*ratsGTe)[i].ineq().getExpr();
01377       Expr leftSide = ineq[0], rightSide = ineq[1];
01378       Rational r;
01379       findRationalBound(leftSide, rightSide, e, r); 
01380       if(numLeft==0 || r<lub) {
01381   lub = r;
01382   strictUB = isLT(ineq);
01383       }
01384       numLeft++;
01385     }
01386     TRACE("model", "   =>Upper bound ", lub.toString(), "");
01387   }
01388   if(!left && !right) {
01389       lub = 0; 
01390       glb = 0;
01391   }
01392   if(!left && right) {lub = glb +2;}
01393   if(!right && left)  {glb =  lub-2;}
01394   DebugAssert(glb <= lub, "Greatest lower bound needs to be smaller "
01395         "than least upper bound"); 
01396   return strictLB;
01397 }
01398 
01399 void TheoryArithNew::assignVariables(std::vector<Expr>&v)
01400 {
01401   int count = 0;
01402   while (v.size() > 0) {
01403     std::vector<Expr> bottom;
01404     d_graph.selectSmallest(v, bottom);
01405     TRACE("model", "Finding variables to assign. Iteration # ", count, "");
01406     for(unsigned int i = 0; i<bottom.size(); i++) {
01407       Expr e = bottom[i];
01408       TRACE("model", "Found: ", e, "");
01409       // Check if it is already a concrete constant
01410       if(e.isRational()) continue;
01411       
01412       Rational lub, glb;
01413       bool strictLB;
01414       strictLB = findBounds(e, lub, glb);
01415       Rational mid;
01416       if(isInteger(e)) {
01417   if(strictLB && glb.isInteger())
01418     mid = glb + 1;
01419   else
01420     mid = ceil(glb);
01421       }
01422       else
01423   mid = (lub + glb)/2;
01424       TRACE("model", "Assigning mid = ", mid, " {");
01425       assignValue(e, rat(mid));
01426       TRACE("model", "Assigned find(e) = ", findExpr(e), " }");
01427       if(inconsistent()) return; // Punt immediately if failed
01428     }
01429     count++;
01430   }
01431 }
01432 
01433 void TheoryArithNew::computeModelBasic(const std::vector<Expr>& v)
01434 {
01435   d_inModelCreation = true;
01436   vector<Expr> reps;
01437   TRACE("model", "Arith=>computeModel ", "", "{");
01438   for(unsigned int i=0; i <v.size(); ++i) {
01439     const Expr& e = v[i];
01440     if(findExpr(e) == e) {
01441       TRACE("model", "arith variable:", e , "");
01442       reps.push_back(e);
01443     }
01444     else {
01445       TRACE("model", "arith variable:", e , "");
01446       TRACE("model", " ==> is defined by: ", findExpr(e) , "");
01447     }
01448   }
01449   assignVariables(reps);
01450   TRACE("model", "Arith=>computeModel", "", "}");
01451   d_inModelCreation = false;
01452 }
01453 
01454 // For any arith expression 'e', if the subexpressions are assigned
01455 // concrete values, then find(e) must already be a concrete value.
01456 void TheoryArithNew::computeModel(const Expr& e, vector<Expr>& vars) {
01457   DebugAssert(findExpr(e).isRational(), "TheoryArithNew::computeModel("
01458         +e.toString()+")\n e is not assigned concrete value.\n"
01459         +" find(e) = "+findExpr(e).toString());
01460   assignValue(simplify(e));
01461   vars.push_back(e);
01462 }
01463 
01464 /*! accepts a rewrite theorem over eqn|ineqn and normalizes it
01465  *  and returns a theorem to that effect. assumes e is non-trivial
01466  *  i.e. e is not '0=const' or 'const=0' or '0 <= const' etc.
01467  */
01468 Theorem TheoryArithNew::normalize(const Expr& e, NormalizationType type) {
01469   
01470   //e is an eqn or ineqn. e is not a trivial eqn or ineqn
01471     //trivial means 0 = const or 0 <= const.
01472   
01473     // Trace the normalization on the arithm trace flag
01474     TRACE("arith", "normalize(", e, ") {"); 
01475   
01476     // The constraint must be an equality or inequality
01477     DebugAssert(isIneq(e), "normalize: input must be an inequality: " + e.toString());
01478   
01479     // The right side must be a sum or a multiplication 
01480     DebugAssert(isPlus(e[1]) || (isMult(e[1]) && e[1][0].isRational()), "normalize: right side must be a sum or a mult: " + e.toString());
01481   
01482     // The left side must be 0
01483     DebugAssert(e[0].isRational() && 0 == e[0].getRational(), "normalize: e[0] must be 0" + e.toString());
01484   
01485     // Compute the factor to use for normalizing the inequality  
01486     Expr factor;
01487     // If a mult, just take the coefficient
01488     if (isMult(e[1])) factor = rat(1/e[1][0].getRational());
01489     // Otherwise compute it
01490     else factor = computeNormalFactor(e[1], type);
01491   
01492     // Trace the rezult on the arith flag
01493     TRACE("arith", "normalize: factor = ", factor, "");
01494     
01495     // The theorem we will be creating (reflexivity, just in case)
01496     Theorem thm;
01497   
01498     // Now multiply the equality by the factor, unless it is 1
01499     if(factor.getRational() != 1)
01500       switch(e.getKind()) {
01501         
01502         case LE:
01503         case LT:
01504         case GE:
01505         case GT:
01506                           
01507             // Multiply inequality by the factor  
01508             thm = d_rules->multIneqn(e, factor);
01509             
01510             // And canonize the result
01511             thm = canonPredEquiv(thm);
01512       
01513             // Inequalities case break
01514             break;
01515         
01516         default:
01517             
01518             // How did we get here
01519             FatalAssert(false, "normalize: control should not reach here" + e.toString());
01520             
01521             // Default case break
01522             break;
01523       }
01524     else 
01525       // If rational is 1 then nothing to be done
01526       thm = reflexivityRule(e);
01527 
01528   
01529   // Trace the resulting theorem on the arith trace flag
01530   TRACE("arith", "normalize => ", thm, " }");
01531   
01532   // Return the explaining theorem
01533   return(thm);
01534 }
01535 
01536 
01537 Theorem TheoryArithNew::normalize(const Theorem& eIffEqn, NormalizationType type) {
01538   return transitivityRule(eIffEqn, normalize(eIffEqn.getRHS(), type));
01539 }
01540 
01541 Theorem TheoryArithNew::rafineIntegerConstraints(const Theorem& thm) {
01542   
01543   // The resulting theorem
01544   Theorem result = thm;
01545   
01546   // Get the constraint
01547   const Expr& constr = result.getRHS();
01548   
01549   // Get the proof that this constraint is an integer constraint 
01550   Theorem isIntConstraintThm = isIntegerThm(constr[1]);
01551   
01552   // If not an integer, just return the same theorem
01553   if (isIntConstraintThm.isNull()) return result;
01554   
01555   // Trace the integer
01556   TRACE("integer", "TheoryArithNew::rafineIntegerConstraints(", constr, ")");
01557   TRACE("integer", "TheoryArithNew::rafineIntegerConstraints: int proof:", isIntConstraintThm, "");
01558   
01559   // Get the left-hand of the constraint (the rational)
01560   Rational r = constr[0].getRational();
01561   
01562   // If it is a strict inequality, make it non-strict
01563   if (constr.getKind() == LT || constr.getKind() == GT || !r.isInteger())
01564     result = transitivityRule(result, d_rules->rafineStrictInteger(isIntConstraintThm, constr));
01565 
01566   // Return the result    
01567   return result;
01568 }
01569 
01570 Theorem TheoryArithNew::rewrite(const Expr& e) {
01571   
01572     // Leaves are assumeed to be already simplified
01573     //DebugAssert(leavesAreSimp(e), "Expected leaves to be simplified");
01574   
01575     // Trace the rewrites on the arith flag
01576     TRACE("arith", "TheoryArithNew::rewrite(", e, ") {");
01577   
01578     // The resulting theorem object
01579     Theorem thm;
01580     
01581     // Are we in the NOT expression
01582     bool isNot = false;
01583   
01584     // If the expression is not a term, i.e a literal  
01585     if (!e.isTerm()) {
01586        
01587       // If the expression is not a literal just return the reflexivity theorem
01588       if (!e.isAbsLiteral()) { 
01589         
01590         // Set the expression REWRITE NORMAL FLAG
01591         e.setRewriteNormal();
01592         
01593         // Create the reflaxivity rule
01594           thm = reflexivityRule(e);
01595         
01596           // Trace the non-literal rewrite 
01597           TRACE("arith", "TheoryArithNew::rewrite[non-literal] => ", thm, " }");
01598         
01599           // Return the theorem
01600           return thm;
01601       }
01602     
01603       // Its a literal, switch the arithmetic relations for rewrite
01604       switch(e.getKind()) {
01605     
01606         // Equality
01607         case EQ: {
01608         
01609           // Rewrite equality as two inequalities
01610           thm = d_rules->eqToIneq(e);
01611           Expr andExpr = thm.getRHS();
01612     
01613           // Rewrite the left inequality
01614           Expr leExpr = andExpr[0];
01615           const Theorem& thmLeft = simplify(leExpr);
01616           
01617           // Rewrite the right inequality 
01618           Expr geExpr = andExpr[1]; 
01619           const Theorem& thmRight = simplify(geExpr);         
01620         
01621           // Do the substitution
01622           thm = transitivityRule(thm, substitutivityRule(andExpr, thmLeft, thmRight));
01623               
01624           // EQ case break
01625           break;
01626         }
01627     
01628         // Negation of an atomic formula
01629         case NOT:    
01630 
01631         // If here, the equality should have already been rewritten as two disequalitites
01632         DebugAssert(e[0].getKind() != EQ, "TheoryArithNew::rewrite, not expecting equality under negation");
01633           
01634         // Negate the inequality and continue with the normal case
01635         thm = d_rules->negatedInequality(e);
01636       
01637         // IMPORTANT, LE, LT, GE, GT MUST BE UNDER THIS
01638         isNot = true;
01639       
01640         case LT:
01641         case GT:
01642         case LE:
01643         case GE:
01644         
01645         // Move everything to the right side
01646         if (isNot)
01647           thm = transitivityRule(thm, d_rules->rightMinusLeft(thm.getRHS())); 
01648         else
01649           thm = d_rules->rightMinusLeft(e);
01650 
01651             // Canonise children again
01652             thm = canonPredEquiv(thm);
01653    
01654             // If a trivial inequation just return true or false
01655             if ((thm.getRHS())[1].isRational()) 
01656           thm = transitivityRule(thm, d_rules->constPredicate(thm.getRHS()));
01657             else { // It's a non-trivial inequation
01658               
01659               // Normalize the inequality 
01660           thm = normalize(thm, NORMALIZE_UNIT);
01661         
01662           // Get the left and right side
01663           const Expr& normalised = thm.getRHS();
01664           const Expr& rightSide = normalised[1]; 
01665           const Expr& leftSide  = normalised[0];
01666         
01667           // If the right side is a sum, move the rational to the right side
01668           if (isPlus(rightSide)) {
01669             // Check if the fist of the sum is a rational
01670             if (rightSide[0].isRational()) {
01671               // Add the negative constant to both sides
01672               thm = transitivityRule(thm, d_rules->plusPredicate(leftSide, rightSide, rat(-rightSide[0].getRational()), thm.getRHS().getKind()));    
01673               // Canonize the left side
01674               const Theorem& thmLeft  = d_rules->canonPlus(thm.getRHS()[0]);
01675               // Canonize the right side
01676               const Theorem& thmRight = d_rules->canonPlus(thm.getRHS()[1]); 
01677               // Sunstitute the canonised into the expression
01678               thm = transitivityRule(thm, substitutivityRule(thm.getRHS(), thmLeft, thmRight));
01679             }
01680           }
01681             }
01682           
01683             // If a strict inequality on integers, or bounded by a non-integer, rafine it to a non-strict one
01684 //            thm = rafineIntegerConstraints(thm);
01685             
01686             // EQ, LE, LT, GE, GT case break        
01687             break;
01688     
01689         case IS_INTEGER:
01690         
01691           // TRACE
01692           TRACE("integer", "Got ", e.toString(), "");
01693           TRACE("integer", "Type ", e[0].getType().toString(), ""); 
01694         
01695           // TODO: What with the integers
01696         thm = d_rules->dummyTheorem(e);
01697           
01698           // IS_INTEGER case break
01699           break;
01700     
01701         default:
01702             
01703             // How did we get here
01704             FatalAssert(false, "Theory_Arith::rewrite: control should not reach here");
01705       
01706             // default break
01707             break;
01708             
01709       } // End relation case
01710       
01711     } else { // Expression is a term 
01712       
01713       // Terms that don't contain formulas are canonised via the canon() function 
01714       if (e.isAtomic()) thm = canon(e);
01715       // Otherwise just return the same expression
01716       else thm = reflexivityRule(e);
01717     }
01718   
01719     // Compact the theorem into one rule
01720     //thm = d_rules->trustedRewrite(e, thm.getRHS());
01721   
01722     // Arith canonization is idempotent, the theory should stay the same
01723     if (theoryOf(thm.getRHS()) == this)
01724       thm.getRHS().setRewriteNormal();
01725     
01726     // Finished, trace the end of rewrite on the arith flag 
01727     TRACE("arith", "TheoryArithNew::rewrite => ", thm, " }");
01728   
01729     // Return the final theorem
01730     return thm;
01731 }
01732 
01733 
01734 void TheoryArithNew::setup(const Expr& e)
01735 {
01736   //If the expression is not a term but rather a predicate
01737     if (!e.isTerm()) {
01738       
01739       // If not or equality, just return
01740       if (e.isNot() || e.isEq()) return;
01741     
01742       // TODO: Integer::eqToIneq
01743       if (isIntPred(e)) return;
01744     
01745       // Check if the expression is canonised as (SUM t1 ... tn) @ b
01746       DebugAssert(isIneq(e) && e[0].isRational(), "TheoryArithNew::setup: b @ (sum t1 ... tn) :" + e.toString());
01747     
01748       // Add the sum to the notify list of e
01749       e[1].addToNotify(this, e);
01750       
01751     } else {
01752       
01753       // The arity of the expression 
01754       int arity(e.arity());
01755       
01756       // Go through all the children and add this expression to their notify lists 
01757       for (int k = 0 ; k < arity; k ++) {
01758         
01759         // Add the to the notify list of the children 
01760         e[k].addToNotify(this, e);
01761         
01762         // Trace this notification add
01763         TRACE("arith setup", "e["+int2string(k)+"]: ", *(e[k].getNotify()), "");
01764       }
01765     }
01766 }
01767 
01768 
01769 void TheoryArithNew::update(const Theorem& e, const Expr& d)
01770 {
01771   if (inconsistent()) return;
01772   IF_DEBUG(debugger.counter("arith update total")++;)
01773   if (!d.hasFind()) return;
01774   if (isIneq(d)) {
01775     // Substitute e[1] for e[0] in d and enqueue new inequality
01776     DebugAssert(e.getLHS() == d[1], "Mismatch");
01777     Theorem thm = find(d);
01778     //    DebugAssert(thm.getRHS() == trueExpr(), "Expected find = true");
01779     vector<unsigned> changed;
01780     vector<Theorem> children;
01781     changed.push_back(1);
01782     children.push_back(e);
01783     Theorem thm2 = substitutivityRule(d, changed, children);
01784     if (thm.getRHS() == trueExpr()) {
01785       enqueueFact(iffMP(getCommonRules()->iffTrueElim(thm), thm2));
01786     }
01787     else {
01788       enqueueFact(getCommonRules()->iffFalseElim(
01789         transitivityRule(symmetryRule(thm2), thm)));
01790     }
01791     IF_DEBUG(debugger.counter("arith update ineq")++;)
01792   }
01793   else if (find(d).getRHS() == d) {
01794     // Substitute e[1] for e[0] in d and assert the result equal to d
01795     Theorem thm = canonSimp(d);
01796     TRACE("arith", "TheoryArithNew::update(): thm = ", thm, "");
01797     DebugAssert(leavesAreSimp(thm.getRHS()), "updateHelper error: "
01798     +thm.getExpr().toString());
01799     assertEqualities(transitivityRule(thm, rewrite(thm.getRHS())));
01800     IF_DEBUG(debugger.counter("arith update find(d)=d")++;)
01801   }
01802 }
01803 
01804 
01805 Theorem TheoryArithNew::solve(const Theorem& thm)
01806 {
01807   DebugAssert(thm.isRewrite() && thm.getLHS().isTerm(), "");
01808   const Expr& lhs = thm.getLHS();
01809   const Expr& rhs = thm.getRHS();
01810 
01811   // Check for already solved equalities.
01812 
01813   // Have to be careful about the types: integer variable cannot be
01814   // assigned a real term.  Also, watch for e[0] being a subexpression
01815   // of e[1]: this would create an unsimplifiable expression.
01816   if (isLeaf(lhs) && !isLeafIn(lhs, rhs) 
01817       && (lhs.getType() != intType() || isInteger(rhs))
01818       // && !e[0].subExprOf(e[1])
01819       )
01820     return thm;
01821 
01822   // Symmetric version is already solved
01823   if (isLeaf(rhs) && !isLeafIn(rhs, lhs)
01824       && (rhs.getType() != intType() || isInteger(lhs))
01825       // && !e[1].subExprOf(e[0])
01826       )
01827     return symmetryRule(thm);
01828 
01829   return doSolve(thm);
01830 }
01831 
01832  
01833 void TheoryArithNew::computeModelTerm(const Expr& e, std::vector<Expr>& v) {
01834   switch(e.getKind()) {
01835   case RATIONAL_EXPR: // Skip the constants
01836     break;
01837   case PLUS:
01838   case MULT:
01839   case DIVIDE:
01840   case POW: // This is not a variable; extract the variables from children
01841     for(Expr::iterator i=e.begin(), iend=e.end(); i!=iend; ++i)
01842       // getModelTerm(*i, v);
01843       v.push_back(*i);
01844     break;
01845   default: { // Otherwise it's a variable.  Check if it has a find pointer
01846     Expr e2(findExpr(e));
01847     if(e==e2) {
01848       TRACE("model", "TheoryArithNew::computeModelTerm(", e, "): a variable");
01849       // Leave it alone (it has no descendants)
01850       // v.push_back(e);
01851     } else {
01852       TRACE("model", "TheoryArithNew::computeModelTerm("+e.toString()
01853       +"): has find pointer to ", e2, "");
01854       v.push_back(e2);
01855     }
01856   }
01857   }
01858 }
01859 
01860 Expr TheoryArithNew::computeTypePred(const Type& t, const Expr& e) {
01861   Expr tExpr = t.getExpr();
01862   switch(tExpr.getKind()) {
01863   case INT:  
01864     return Expr(IS_INTEGER, e);
01865   case SUBRANGE: {
01866     std::vector<Expr> kids;
01867     kids.push_back(Expr(IS_INTEGER, e));
01868     kids.push_back(leExpr(tExpr[0], e));
01869     kids.push_back(leExpr(e, tExpr[1]));
01870     return andExpr(kids);
01871   }
01872   default:
01873     return e.getEM()->trueExpr();
01874   }
01875 }
01876 
01877 
01878 void TheoryArithNew::checkAssertEqInvariant(const Theorem& e)
01879 {
01880   return;
01881 }
01882 
01883 
01884 void TheoryArithNew::checkType(const Expr& e)
01885 {
01886   switch (e.getKind()) {
01887     case INT:
01888     case REAL:
01889       if (e.arity() > 0) {
01890         throw Exception("Ill-formed arithmetic type: "+e.toString());
01891       }
01892       break;
01893     case SUBRANGE:
01894       if (e.arity() != 2 ||
01895           !isIntegerConst(e[0]) ||
01896           !isIntegerConst(e[1]) ||
01897           e[0].getRational() > e[1].getRational()) {
01898         throw Exception("bad SUBRANGE type expression"+e.toString());
01899       }
01900       break;
01901     default:
01902       DebugAssert(false, "Unexpected kind in TheoryArithNew::checkType"
01903                   +getEM()->getKindName(e.getKind()));
01904   }
01905 }
01906 
01907 
01908 Cardinality TheoryArithNew::finiteTypeInfo(Expr& e, Unsigned& n,
01909                                            bool enumerate, bool computeSize)
01910 {
01911   Cardinality card = CARD_INFINITE;
01912   switch (e.getKind()) {
01913     case SUBRANGE: {
01914       card = CARD_FINITE;
01915       Expr typeExpr = e;
01916       if (enumerate) {
01917         Rational r = typeExpr[0].getRational() + n;
01918         if (r <= typeExpr[1].getRational()) {
01919           e = rat(r);
01920         }
01921         else e = Expr();
01922       }
01923       if (computeSize) {
01924         Rational r = typeExpr[1].getRational() - typeExpr[0].getRational() + 1;
01925         n = r.getUnsigned();
01926       }
01927       break;
01928     }
01929     default:
01930       break;
01931   }
01932   return card;
01933 }
01934 
01935 
01936 void TheoryArithNew::computeType(const Expr& e)
01937 {
01938   switch (e.getKind()) {
01939     case REAL_CONST:
01940       e.setType(d_realType);
01941       break;
01942     case RATIONAL_EXPR:
01943       if(e.getRational().isInteger())
01944         e.setType(d_intType);
01945       else
01946         e.setType(d_realType);
01947       break;
01948     case UMINUS:
01949     case PLUS:
01950     case MINUS:
01951     case MULT:
01952     case POW: {
01953       bool isInt = true;
01954       for(int k = 0; k < e.arity(); ++k) {
01955         if(d_realType != getBaseType(e[k]))
01956           throw TypecheckException("Expecting type REAL with `" +
01957                                    getEM()->getKindName(e.getKind()) + "',\n"+
01958                                    "but got a " + getBaseType(e[k]).toString()+ 
01959                                    " for:\n" + e.toString());
01960         if(isInt && !isInteger(e[k]))
01961           isInt = false;
01962       }
01963       if(isInt)
01964         e.setType(d_intType);
01965       else
01966         e.setType(d_realType);
01967       break;
01968     }
01969     case DIVIDE: {
01970       Expr numerator = e[0];
01971       Expr denominator = e[1];
01972       if (getBaseType(numerator) != d_realType ||
01973           getBaseType(denominator) != d_realType) {
01974         throw TypecheckException("Expecting only REAL types with `DIVIDE',\n"
01975                                  "but got " + getBaseType(numerator).toString()+ 
01976                                  " and " + getBaseType(denominator).toString() +
01977                                  " for:\n" + e.toString());
01978       }
01979       if(denominator.isRational() && 1 == denominator.getRational())
01980         e.setType(numerator.getType());
01981       else
01982         e.setType(d_realType);
01983       break;
01984     }
01985     case LT:
01986     case LE:
01987     case GT:
01988     case GE:
01989     case GRAY_SHADOW:
01990       // Need to know types for all exprs -Clark
01991       //    e.setType(boolType());
01992       //    break;
01993     case DARK_SHADOW:
01994       for (int k = 0; k < e.arity(); ++k) {
01995         if (d_realType != getBaseType(e[k]))
01996           throw TypecheckException("Expecting type REAL with `" +
01997                                    getEM()->getKindName(e.getKind()) + "',\n"+
01998                                    "but got a " + getBaseType(e[k]).toString()+ 
01999                                    " for:\n" + e.toString());
02000       }
02001       
02002       e.setType(boolType());
02003       break;
02004     case IS_INTEGER:
02005       if(d_realType != getBaseType(e[0]))
02006         throw TypecheckException("Expected type REAL, but got "
02007                                  +getBaseType(e[0]).toString()
02008                                  +"\n\nExpr = "+e.toString());
02009       e.setType(boolType());
02010       break;
02011     default:
02012       DebugAssert(false,"TheoryArithNew::computeType: unexpected expression:\n "
02013                   +e.toString());
02014       break;
02015   }
02016 }
02017 
02018 Type TheoryArithNew::computeBaseType(const Type& t) {
02019   IF_DEBUG(int kind = t.getExpr().getKind();)
02020   DebugAssert(kind==INT || kind==REAL || kind==SUBRANGE,
02021         "TheoryArithNew::computeBaseType("+t.toString()+")");
02022   return realType();
02023 }
02024 
02025 Expr TheoryArithNew::computeTCC(const Expr& e) {
02026   Expr tcc(Theory::computeTCC(e));
02027   switch(e.getKind()) {
02028   case DIVIDE:
02029     DebugAssert(e.arity() == 2, "");
02030     return tcc.andExpr(!(e[1].eqExpr(rat(0))));
02031   default:
02032     return tcc;
02033   }
02034 }
02035 
02036 ///////////////////////////////////////////////////////////////////////////////
02037 //parseExprOp:
02038 //translating special Exprs to regular EXPR??
02039 ///////////////////////////////////////////////////////////////////////////////
02040 Expr TheoryArithNew::parseExprOp(const Expr& e) {
02041   TRACE("parser", "TheoryArithNew::parseExprOp(", e, ")");
02042   //std::cout << "Were here";
02043   // If the expression is not a list, it must have been already
02044   // parsed, so just return it as is.
02045   switch(e.getKind()) {
02046   case ID: {
02047     int kind = getEM()->getKind(e[0].getString());
02048     switch(kind) {
02049     case NULL_KIND: return e; // nothing to do
02050     case REAL:
02051     case INT:
02052     case NEGINF: 
02053     case POSINF: return getEM()->newLeafExpr(kind);
02054     default:
02055       DebugAssert(false, "Bad use of bare keyword: "+e.toString());
02056       return e;
02057     }
02058   }
02059   case RAW_LIST: break; // break out of switch, do the hard work
02060   default:
02061     return e;
02062   }
02063 
02064   DebugAssert(e.getKind() == RAW_LIST && e.arity() > 0,
02065         "TheoryArithNew::parseExprOp:\n e = "+e.toString());
02066   
02067   const Expr& c1 = e[0][0];
02068   int kind = getEM()->getKind(c1.getString());
02069   switch(kind) {
02070     case UMINUS: {
02071       if(e.arity() != 2)
02072   throw ParserException("UMINUS requires exactly one argument: "
02073       +e.toString());
02074       return uminusExpr(parseExpr(e[1])); 
02075     }
02076     case PLUS: {
02077       vector<Expr> k;
02078       Expr::iterator i = e.begin(), iend=e.end();
02079       // Skip first element of the vector of kids in 'e'.
02080       // The first element is the operator.
02081       ++i; 
02082       // Parse the kids of e and push them into the vector 'k'
02083       for(; i!=iend; ++i) k.push_back(parseExpr(*i));
02084       return plusExpr(k); 
02085     }
02086     case MINUS: {
02087       if(e.arity() == 2)
02088   return uminusExpr(parseExpr(e[1]));
02089       else if(e.arity() == 3)
02090   return minusExpr(parseExpr(e[1]), parseExpr(e[2]));
02091       else
02092   throw ParserException("MINUS requires one or two arguments:"
02093       +e.toString());
02094     }
02095     case MULT: {
02096       vector<Expr> k;
02097       Expr::iterator i = e.begin(), iend=e.end();
02098       // Skip first element of the vector of kids in 'e'.
02099       // The first element is the operator.
02100       ++i; 
02101       // Parse the kids of e and push them into the vector 'k'
02102       for(; i!=iend; ++i) k.push_back(parseExpr(*i));
02103       return multExpr(k);
02104     }
02105     case POW: { 
02106       return powExpr(parseExpr(e[1]), parseExpr(e[2])); 
02107     }
02108     case DIVIDE:
02109       { return divideExpr(parseExpr(e[1]), parseExpr(e[2]));  }
02110     case LT:  
02111       { return ltExpr(parseExpr(e[1]), parseExpr(e[2]));  }
02112     case LE:  
02113       { return leExpr(parseExpr(e[1]), parseExpr(e[2]));  }
02114     case GT:  
02115       { return gtExpr(parseExpr(e[1]), parseExpr(e[2]));  }
02116     case GE:  
02117       { return geExpr(parseExpr(e[1]), parseExpr(e[2]));  }
02118     case INTDIV:
02119     case MOD:
02120     case SUBRANGE: {
02121       vector<Expr> k;
02122       Expr::iterator i = e.begin(), iend=e.end();
02123       // Skip first element of the vector of kids in 'e'.
02124       // The first element is the operator.
02125       ++i; 
02126       // Parse the kids of e and push them into the vector 'k'
02127       for(; i!=iend; ++i) 
02128         k.push_back(parseExpr(*i));
02129       return Expr(kind, k, e.getEM());
02130     }
02131     case IS_INTEGER: {
02132       if(e.arity() != 2)
02133   throw ParserException("IS_INTEGER requires exactly one argument: "
02134       +e.toString());
02135       return Expr(IS_INTEGER, parseExpr(e[1]));
02136     }
02137     default:
02138       DebugAssert(false,
02139         "TheoryArithNew::parseExprOp: invalid input " + e.toString());
02140       break;
02141   }
02142   return e;
02143 }
02144 
02145 ///////////////////////////////////////////////////////////////////////////////
02146 // Pretty-printing                                                           //
02147 ///////////////////////////////////////////////////////////////////////////////
02148 
02149 
02150 ExprStream& TheoryArithNew::print(ExprStream& os, const Expr& e) {
02151   switch(os.lang()) {
02152     case SIMPLIFY_LANG:
02153       switch(e.getKind()) {
02154       case RATIONAL_EXPR:
02155   e.print(os);
02156   break;
02157       case SUBRANGE:
02158   os <<"ERROR:SUBRANGE:not supported in Simplify\n";
02159   break;
02160       case IS_INTEGER:
02161   os <<"ERROR:IS_INTEGER:not supported in Simplify\n";
02162   break;
02163       case PLUS:  {
02164   int i=0, iend=e.arity();
02165   os << "(+ "; 
02166   if(i!=iend) os << e[i];
02167   ++i;
02168   for(; i!=iend; ++i) os << " " << e[i];
02169   os <<  ")";
02170   break;
02171       }
02172       case MINUS:
02173   os << "(- " << e[0] << " " << e[1]<< ")";
02174   break;
02175       case UMINUS:
02176   os << "-" << e[0] ;
02177   break;
02178       case MULT:  {
02179   int i=0, iend=e.arity();
02180   os << "(* " ;
02181   if(i!=iend) os << e[i];
02182   ++i;
02183   for(; i!=iend; ++i) os << " " << e[i];
02184   os <<  ")";
02185   break;
02186       }
02187       case POW:
02188           os << "(" << push << e[1] << space << "^ " << e[0] << push << ")";
02189           break;
02190       case DIVIDE:
02191   os << "(" << push << e[0] << space << "/ " << e[1] << push << ")";
02192   break;
02193       case LT:
02194   if (isInt(e[0].getType()) || isInt(e[1].getType())) {
02195   }
02196   os << "(< " << e[0] << " " << e[1] <<")";
02197   break;
02198       case LE:
02199           os << "(<= " << e[0]  << " " << e[1] << ")";
02200           break;
02201       case GT:
02202   os << "(> " << e[0] << " " << e[1] << ")";
02203   break;
02204       case GE:
02205   os << "(>= " << e[0] << " " << e[1]  << ")";
02206   break;
02207       case DARK_SHADOW:
02208       case GRAY_SHADOW:
02209   os <<"ERROR:SHADOW:not supported in Simplify\n";
02210   break;
02211       default:
02212   // Print the top node in the default LISP format, continue with
02213   // pretty-printing for children.
02214           e.print(os);
02215     
02216           break;
02217       } 
02218       break; // end of case SIMPLIFY_LANG
02219 
02220 
02221     case TPTP_LANG:
02222       switch(e.getKind()) {
02223       case RATIONAL_EXPR:
02224   e.print(os);
02225   break;
02226       case SUBRANGE:
02227   os <<"ERROR:SUBRANGE:not supported in TPTP\n";
02228   break;
02229       case IS_INTEGER:
02230   os <<"ERROR:IS_INTEGER:not supported in TPTP\n";
02231   break;
02232       case PLUS:  {
02233   if(!isInteger(e[0])){
02234     os<<"ERRPR:plus only supports inteters now in TPTP\n";
02235     break;
02236   }
02237   
02238   int i=0, iend=e.arity();
02239   if(iend <=1){
02240     os<<"ERROR,plus must have more than two numbers in TPTP\n";
02241     break;
02242   }
02243 
02244   for(i=0; i <= iend-2; ++i){
02245     os << "$plus_int("; 
02246     os << e[i] << ",";
02247   }
02248 
02249   os<< e[iend-1];
02250 
02251   for(i=0 ; i <= iend-2; ++i){
02252     os << ")"; 
02253   }
02254 
02255   break;
02256       }
02257       case MINUS:
02258   os << "(- " << e[0] << " " << e[1]<< ")";
02259   break;
02260       case UMINUS:
02261   os << "-" << e[0] ;
02262   break;
02263       case MULT:  {
02264   int i=0, iend=e.arity();
02265   os << "(* " ;
02266   if(i!=iend) os << e[i];
02267   ++i;
02268   for(; i!=iend; ++i) os << " " << e[i];
02269   os <<  ")";
02270   break;
02271       }
02272       case POW:
02273           os << "(" << push << e[1] << space << "^ " << e[0] << push << ")";
02274           break;
02275       case DIVIDE:
02276   os << "(" << push << e[0] << space << "/ " << e[1] << push << ")";
02277   break;
02278       case LT:
02279   if (isInt(e[0].getType()) || isInt(e[1].getType())) {
02280   }
02281   os << "(< " << e[0] << " " << e[1] <<")";
02282   break;
02283       case LE:
02284           os << "(<= " << e[0]  << " " << e[1] << ")";
02285           break;
02286       case GT:
02287   os << "(> " << e[0] << " " << e[1] << ")";
02288   break;
02289       case GE:
02290   os << "(>= " << e[0] << " " << e[1]  << ")";
02291   break;
02292       case DARK_SHADOW:
02293       case GRAY_SHADOW:
02294   os <<"ERROR:SHADOW:not supported in TPTP\n";
02295   break;
02296       default:
02297   // Print the top node in the default LISP format, continue with
02298   // pretty-printing for children.
02299           e.print(os);
02300     
02301           break;
02302       } 
02303       break; // end of case TPTP_LANG
02304 
02305       
02306     case PRESENTATION_LANG:
02307       switch(e.getKind()) {
02308         case REAL:
02309         case INT:
02310         case RATIONAL_EXPR:
02311         case NEGINF:
02312         case POSINF:
02313           e.print(os);
02314           break;
02315         case SUBRANGE:
02316           if(e.arity() != 2) e.printAST(os);
02317           else 
02318             os << "[" << push << e[0] << ".." << e[1] << push << "]";
02319           break;
02320         case IS_INTEGER:
02321     if(e.arity() == 1)
02322       os << "IS_INTEGER(" << push << e[0] << push << ")";
02323     else
02324       e.printAST(os);
02325     break;
02326         case PLUS:  {
02327           int i=0, iend=e.arity();
02328           os << "(" << push;
02329           if(i!=iend) os << e[i];
02330           ++i;
02331           for(; i!=iend; ++i) os << space << "+ " << e[i];
02332           os << push << ")";
02333           break;
02334         }
02335         case MINUS:
02336           os << "(" << push << e[0] << space << "- " << e[1] << push << ")";
02337           break;
02338         case UMINUS:
02339           os << "-(" << push << e[0] << push << ")";
02340           break;
02341         case MULT:  {
02342           int i=0, iend=e.arity();
02343           os << "(" << push;
02344           if(i!=iend) os << e[i];
02345           ++i;
02346           for(; i!=iend; ++i) os << space << "* " << e[i];
02347           os << push << ")";
02348           break;
02349         }
02350         case POW:
02351           os << "(" << push << e[1] << space << "^ " << e[0] << push << ")";
02352           break;
02353         case DIVIDE:
02354           os << "(" << push << e[0] << space << "/ " << e[1] << push << ")";
02355           break;
02356         case LT:
02357           if (isInt(e[0].getType()) || isInt(e[1].getType())) {
02358           }
02359           os << "(" << push << e[0] << space << "< " << e[1] << push << ")";
02360           break;
02361         case LE:
02362           os << "(" << push << e[0] << space << "<= " << e[1] << push << ")";
02363           break;
02364         case GT:
02365           os << "(" << push << e[0] << space << "> " << e[1] << push << ")";
02366           break;
02367         case GE:
02368           os << "(" << push << e[0] << space << ">= " << e[1] << push << ")";
02369           break;
02370         case DARK_SHADOW:
02371     os << "DARK_SHADOW(" << push << e[0] << ", " << space << e[1] << push << ")";
02372     break;
02373         case GRAY_SHADOW:
02374     os << "GRAY_SHADOW(" << push << e[0] << ","  << space << e[1]
02375        << "," << space << e[2] << "," << space << e[3] << push << ")";
02376     break;
02377         default:
02378           // Print the top node in the default LISP format, continue with
02379           // pretty-printing for children.
02380           e.printAST(os);
02381 
02382           break;
02383       } 
02384       break; // end of case PRESENTATION_LANG
02385     case SMTLIB_LANG:
02386     case SMTLIB_V2_LANG: {
02387       switch(e.getKind()) {
02388         case REAL_CONST:
02389           printRational(os, e[0].getRational(), true);
02390           break;
02391         case RATIONAL_EXPR:
02392           printRational(os, e.getRational());
02393           break;
02394         case REAL:
02395           os << "Real";
02396           break;
02397         case INT:
02398           os << "Int";
02399           break;
02400         case SUBRANGE:
02401           throw SmtlibException("TheoryArithNew::print: SMTLIB: SUBRANGE not implemented");
02402 //           if(e.arity() != 2) e.print(os);
02403 //           else 
02404 //             os << "(" << push << "SUBRANGE" << space << e[0]
02405 //         << space << e[1] << push << ")";
02406           break;
02407         case IS_INTEGER:
02408     if(e.arity() == 1)
02409       os << "(" << push << "IsInt" << space << e[0] << push << ")";
02410     else
02411             throw SmtlibException("TheoryArithNew::print: SMTLIB: IS_INTEGER used unexpectedly");
02412     break;
02413         case PLUS:  {
02414           if(e.arity() == 1 && os.lang() == SMTLIB_V2_LANG) {
02415             os << e[0];
02416           } else {
02417             os << "(" << push << "+";
02418             Expr::iterator i = e.begin(), iend = e.end();
02419             for(; i!=iend; ++i) {
02420               os << space << (*i);
02421             }
02422             os << push << ")";
02423           }
02424           break;
02425         }
02426         case MINUS: {
02427           os << "(" << push << "- " << e[0] << space << e[1] << push << ")";
02428           break;
02429         }
02430         case UMINUS: {
02431           os << "(" << push << "-" << space << e[0] << push << ")";
02432           break;
02433         }
02434         case MULT:  {
02435           int i=0, iend=e.arity();
02436           if(iend == 1 && os.lang() == SMTLIB_V2_LANG) {
02437             os << e[0];
02438           } else {
02439             for(; i!=iend; ++i) {
02440               if (i < iend-1) {
02441                 os << "(" << push << "*";
02442               }
02443               os << space << e[i];
02444             }
02445             for (i=0; i < iend-1; ++i) os << push << ")";
02446           }
02447           break;
02448         }
02449         case POW:
02450           throw SmtlibException("TheoryArithNew::print: SMTLIB: POW not supported");
02451           //          os << "(" << push << "^ " << e[1] << space << e[0] << push << ")";
02452           break;
02453         case DIVIDE: {
02454           throw SmtlibException("TheoryArithNew::print: SMTLIB: unexpected use of DIVIDE");
02455           break;
02456         }
02457         case LT: {
02458           Rational r;
02459           os << "(" << push << "<" << space;
02460           os << e[0] << space << e[1] << push << ")";
02461           break;
02462         }
02463         case LE: {
02464           Rational r;
02465           os << "(" << push << "<=" << space;
02466           os << e[0] << space << e[1] << push << ")";
02467           break;
02468         }
02469         case GT: {
02470           Rational r;
02471           os << "(" << push << ">" << space;
02472           os << e[0] << space << e[1] << push << ")";
02473           break;
02474         }
02475         case GE: {
02476           Rational r;
02477           os << "(" << push << ">=" << space;
02478           os << e[0] << space << e[1] << push << ")";
02479           break;
02480         }
02481         case DARK_SHADOW:
02482           throw SmtlibException("TheoryArithNew::print: SMTLIB: DARK_SHADOW not supported");
02483     os << "(" << push << "DARK_SHADOW" << space << e[0]
02484        << space << e[1] << push << ")";
02485     break;
02486         case GRAY_SHADOW:
02487           throw SmtlibException("TheoryArithNew::print: SMTLIB: GRAY_SHADOW not supported");
02488     os << "GRAY_SHADOW(" << push << e[0] << ","  << space << e[1]
02489        << "," << space << e[2] << "," << space << e[3] << push << ")";
02490     break;
02491         default:
02492           throw SmtlibException("TheoryArithNew::print: SMTLIB: default not supported");
02493           // Print the top node in the default LISP format, continue with
02494           // pretty-printing for children.
02495           e.printAST(os);
02496 
02497           break;
02498       } 
02499       break; // end of case SMTLIB_LANG
02500     }
02501     case LISP_LANG:
02502       switch(e.getKind()) {
02503         case REAL:
02504         case INT:
02505         case RATIONAL_EXPR:
02506         case NEGINF:
02507         case POSINF:
02508           e.print(os);
02509           break;
02510         case SUBRANGE:
02511           if(e.arity() != 2) e.printAST(os);
02512           else 
02513             os << "(" << push << "SUBRANGE" << space << e[0]
02514          << space << e[1] << push << ")";
02515           break;
02516         case IS_INTEGER:
02517     if(e.arity() == 1)
02518       os << "(" << push << "IS_INTEGER" << space << e[0] << push << ")";
02519     else
02520       e.printAST(os);
02521     break;
02522         case PLUS:  {
02523           int i=0, iend=e.arity();
02524           os << "(" << push << "+";
02525           for(; i!=iend; ++i) os << space << e[i];
02526           os << push << ")";
02527           break;
02528         }
02529         case MINUS:
02530         //os << "(" << push << e[0] << space << "- " << e[1] << push << ")";
02531     os << "(" << push << "- " << e[0] << space << e[1] << push << ")";
02532           break;
02533         case UMINUS:
02534           os << "(" << push << "-" << space << e[0] << push << ")";
02535           break;
02536         case MULT:  {
02537           int i=0, iend=e.arity();
02538           os << "(" << push << "*";
02539           for(; i!=iend; ++i) os << space << e[i];
02540           os << push << ")";
02541           break;
02542         }
02543         case POW:
02544           os << "(" << push << "^ " << e[1] << space << e[0] << push << ")";
02545           break;
02546         case DIVIDE:
02547           os << "(" << push << "/ " << e[0] << space << e[1] << push << ")";
02548           break;
02549         case LT:
02550           os << "(" << push << "< " << e[0] << space << e[1] << push << ")";
02551           break;
02552         case LE:
02553           os << "(" << push << "<= " << e[0] << space << e[1] << push << ")";
02554           break;
02555         case GT:
02556           os << "(" << push << "> " << e[1]  << space << e[0] << push << ")";
02557           break;
02558         case GE:
02559           os << "(" << push << ">= " << e[0] << space << e[1] << push << ")";
02560           break;
02561         case DARK_SHADOW:
02562     os << "(" << push << "DARK_SHADOW" << space << e[0]
02563        << space << e[1] << push << ")";
02564     break;
02565         case GRAY_SHADOW:
02566     os << "(" << push << "GRAY_SHADOW" << space << e[0] << space
02567        << e[1] << space << e[2] << space << e[3] << push << ")";
02568     break;
02569         default:
02570           // Print the top node in the default LISP format, continue with
02571           // pretty-printing for children.
02572           e.printAST(os);
02573 
02574           break;
02575       } 
02576       break; // end of case LISP_LANG
02577     default:
02578      // Print the top node in the default LISP format, continue with
02579      // pretty-printing for children.
02580        e.printAST(os);
02581   }
02582   return os;
02583 }
02584 
02585 ///////////////////////////////////////////////////////////////////////////////
02586 // SIMPLEX SOLVER                                                            //
02587 ///////////////////////////////////////////////////////////////////////////////
02588 
02589 bool TheoryArithNew::isBasic(const Expr& x) const {
02590   // If it is on the right side of the tableaux the it is basic, non-basic otherwise
02591   return (tableaux.find(x) != tableaux.end());
02592 }
02593 
02594 void TheoryArithNew::pivot(const Expr& x_r, const Expr& x_s) {
02595   
02596   // Check that the variable is non-basic
02597   DebugAssert(isBasic(x_r), "TheoryArithNew::pivot, given variable should be basic" + x_r.toString());
02598   DebugAssert(!isBasic(x_s), "TheoryArithNew::pivot, given variable should be non-basic" + x_s.toString());
02599 
02600   // If trace is on for the simplex, print it out
02601   TRACE("simplex", "TheoryArithNew::pivot(", x_r.toString() + ", " + x_s.toString(), ")");
02602 
02603   // Get the iterator that points to the expression of x_r
02604   TebleauxMap::iterator it = tableaux.find(x_r); 
02605   
02606   // Get the expresiion of x_r
02607   Theorem x_r_Theorem = (*it).second;  
02608   
02609   // Erase the x_r expression from the tableaux
02610   tableaux.erase(x_r); // TODO: Add erase by iterator to ExprHashMap
02611   
02612   // Update the dependencies
02613   updateDependenciesRemove(x_r, x_r_Theorem.getExpr()[1]);
02614   
02615   // Construct the expresison (theorem) of x_s
02616   const Theorem& x_s_Theorem = pivotRule(x_r_Theorem, x_s); 
02617     
02618   // Replace all occurances of x_s with x_s_Expression
02619   substAndCanonizeTableaux(x_s_Theorem);
02620   
02621   // Update the dependencies
02622   updateDependenciesAdd(x_s, x_s_Theorem.getExpr()[1]);
02623   
02624   // Add the expression of x_s to the map
02625   tableaux[x_s] = x_s_Theorem;
02626 }
02627 
02628 void TheoryArithNew::update(const Expr& x_i, const EpsRational& v) {
02629   
02630   // Check that the variable is non-basic
02631   DebugAssert(tableaux.find(x_i) == tableaux.end(), "TheoryArithNew::update, given variable should be non-basic" + x_i.toString());
02632 
02633   // If trace is on for the simplex, print it out
02634   TRACE("simplex", "TheoryArithNew::update(", x_i.toString() + ", " + v.toString(), ")");
02635 
02636   // Remember the value of the x_i variable
02637   EpsRational old_value = getBeta(x_i);
02638 
02639   // If there are dependent variables then do the work 
02640   DependenciesMap::iterator find = dependenciesMap.find(x_i);
02641   if (find != dependenciesMap.end()) {
02642   
02643     // Go through all the variables that depend on x_i
02644     const set<Expr>& dependent = (*find).second;
02645     set<Expr>::const_iterator it     = dependent.begin();
02646     set<Expr>::const_iterator it_end = dependent.end();     
02647     // Fix the values of all the variables
02648     while (it != it_end) {
02649       
02650       // Get the current variable
02651       const Expr& x_j = *it;
02652       
02653       // Get the tableaux coefficient of the of x_i in the row of x_j (the right side ofg the tableaux expression)
02654       const Rational& a_ji = getTableauxEntry(x_j, x_i);
02655       
02656       // Update the beta valuation
02657       EpsRational b(getBeta(x_j)); // TODO: not necessary, beta's are all setup now
02658       EpsRational x_j_new = beta[x_j] = b + (v - old_value) * a_ji;
02659       
02660       // Check if the variable is sat or unsat under the new assignment 
02661       if (x_j_new < getLowerBound(x_j) || getUpperBound(x_j) < x_j_new)
02662         unsatBasicVariables.insert(x_j);
02663       else
02664         unsatBasicVariables.erase(x_j);
02665       
02666       // Go to the next one
02667       it ++;
02668     }
02669   }
02670   
02671   // Set the new value to x_i (x_i) is non_basic, no need to add to unsat set)
02672   beta[x_i] = v;
02673 }
02674       
02675 void TheoryArithNew::pivotAndUpdate(const Expr& x_i, const Expr& x_j, const EpsRational& v) {
02676   
02677   // Variable x_i should be a basic variable (left side of the tableaux) and x_j should be non_basic
02678   DebugAssert(tableaux.find(x_i) != tableaux.end(), "TheoryArithNew::pivotAndUpdate, " + x_i.toString() + " should be a basic variable");
02679   DebugAssert(tableaux.find(x_j) == tableaux.end(), "TheoryArithNew::pivotAndUpdate, " + x_j.toString() + " should be a non-basic variable");
02680 
02681   // If trace is on for the simplex, print it out
02682   TRACE("simplex", "TheoryArithNew::pivotAndUpdate(", x_i.toString() + ", " + x_j.toString() + ", " + v.toString(), ")");
02683 
02684   // The a_ij coefficient of the tableaux
02685   const Rational& a_ij = getTableauxEntry(x_i, x_j);
02686   
02687   // Let theta be the adjustment coefficient
02688   EpsRational theta((v - getBeta(x_i))/a_ij);
02689   
02690   // Set the new value to x_i (x_i becomes non-basic, hance sat)
02691   beta[x_i] = v;
02692   // x_i becomes non-basic, no need ==> it is sat
02693   unsatBasicVariables.erase(x_i);
02694   
02695   // Set the new value to x_j 
02696   EpsRational b = getBeta(x_j);
02697   EpsRational new_x_j = beta[x_j] = b + theta;
02698   
02699   // Check if the variable is sat or unsat under the new assignment 
02700   if (new_x_j < getLowerBound(x_j) || getUpperBound(x_j) < new_x_j)
02701     unsatBasicVariables.insert(x_j);
02702   else
02703     unsatBasicVariables.erase(x_j);
02704   
02705   // Go through all the variables that depend on x_j, and update their value (there will be at least one, i.e. x_i) // TODO: maybe optimise
02706   const set<Expr>& dependent = (*dependenciesMap.find(x_j)).second;
02707   set<Expr>::const_iterator it     = dependent.begin();
02708   set<Expr>::const_iterator it_end = dependent.end();     
02709   // Go throught all the basic variables
02710   while (it != it_end) {
02711     
02712     // Get the current variable
02713     const Expr& x_k = *it; 
02714     
02715     // If the basic variable is different from x_i update its value
02716     if (x_k != x_i) {
02717     
02718       // Get the a_kj coefficient from the tableaux
02719       const Rational& a_kj = getTableauxEntry(x_k, x_j);
02720       
02721       // Adjust the value (check fort sat/unsat, x_k is basic)
02722       b = getBeta(x_k);
02723       EpsRational x_k_new = beta[x_k] = b + theta * a_kj; 
02724       
02725       // Check if the variable is sat or unsat under the new assignment 
02726       if (x_k_new < getLowerBound(x_k) || getUpperBound(x_k) < x_k_new)
02727         unsatBasicVariables.insert(x_k);
02728       else
02729         unsatBasicVariables.erase(x_k);
02730     }
02731   
02732     // Go to the next one
02733     it ++;
02734   }
02735   
02736   // Last thing to do, pivot x_i and x_j
02737   pivot(x_i, x_j);
02738 }
02739       
02740 QueryResult TheoryArithNew::assertUpper(const Expr& x_i, const EpsRational& c, const Theorem& thm) {
02741   
02742   // If trace is on for the simplex, print it out
02743   TRACE("simplex", "TheoryArithNew::assertUpper(", x_i.toString() + ", " + c.toString(), ")");
02744 
02745   // Check if the given expression is actually a variable
02746   DebugAssert(isLeaf(x_i), "TheoryArithNew::assertUpper wrong kind, expected an arithmetic leaf (variable) got " + x_i.toString());
02747   
02748   // Check if the upper bound is worse then the last one
02749   if (getUpperBound(x_i) <= c) return (consistent == UNKNOWN? UNKNOWN : SATISFIABLE); 
02750   
02751   // If the new bound is lower then the lower bound */
02752   if (c < getLowerBound(x_i)) {
02753     // Create the explaining theorem
02754     explanation = d_rules->clashingBounds(getLowerBoundThm(x_i), thm);
02755     // Return unsatisfiable
02756     return UNSATISFIABLE;
02757   }
02758   
02759   // Since it is a tighter bound, propagate what can be 
02760   propagate = true;
02761 
02762   // Set the new upper bound */
02763   upperBound[x_i] = BoundInfo(c, thm);
02764 
02765   // If within the new bounds, return the previous state 
02766   if (getBeta(x_i) <= c) return (consistent == UNKNOWN? UNKNOWN : SATISFIABLE);
02767   
02768   // Otherwise, if the variable is non-basic then update it's value
02769   if (!isBasic(x_i)) update(x_i, c);
02770   // Else its basic, and non-sat, add to the unsat set
02771   else unsatBasicVariables.insert(x_i);
02772   
02773   // Everything went fine, return OK (not complete, means not UNSAT)
02774   return UNKNOWN;
02775 }
02776 
02777 QueryResult TheoryArithNew::assertLower(const Expr& x_i, const EpsRational& c, const Theorem& thm) {
02778 
02779   // Check if the given expression is actually a variable
02780   DebugAssert(isLeaf(x_i), "TheoryArithNew::assertLower wrong kind, expected an arithmetic leaf (variable) got " + x_i.toString());
02781 
02782   // If trace is on for the simplex, print it out
02783   TRACE("simplex", "TheoryArithNew::assertLower(", x_i.toString() + ", " + c.toString(), ")");
02784   
02785   // Check if the upper bound is worse then the last one
02786   if (c <= getLowerBound(x_i)) return (consistent == UNKNOWN? UNKNOWN : SATISFIABLE); 
02787   
02788   // Since it is a tighter bound, propagate what can be 
02789   propagate = true;
02790   
02791   // If the new bound is lower then the  bound */
02792   if (c > getUpperBound(x_i)) { 
02793     // Create the explaining theorem
02794     explanation = d_rules->clashingBounds(thm, getUpperBoundThm(x_i));
02795     // Return unsatisfiable
02796     return UNSATISFIABLE;
02797   }
02798   
02799   // Set the new upper bound */
02800   lowerBound[x_i] = BoundInfo(c, thm);
02801   
02802   // If within the new bounds, return the previous state 
02803   if (c <= getBeta(x_i)) return (consistent == UNKNOWN? UNKNOWN : SATISFIABLE);
02804   
02805   // Otherwise, if the variable is non-basic then update it's value
02806   if (!isBasic(x_i)) update(x_i, c);
02807   // Else its basic, and non-sat, add to the unsat set
02808   else unsatBasicVariables.insert(x_i);
02809   
02810   // Everything went fine, return OK (not complete, means not UNSAT)
02811   return UNKNOWN;
02812 }
02813       
02814 QueryResult TheoryArithNew::assertEqual(const Expr& x_i, const EpsRational& c, const Theorem& thm) {
02815   
02816   // Assert the upper bound
02817   consistent = assertUpper(x_i, c, thm); // TODO: thm: = |- <=
02818   
02819   // If the return value is UNSAT return UNSAT
02820   if (consistent == UNSATISFIABLE) return UNSATISFIABLE;
02821   
02822   // Assert the lower bound
02823   consistent = assertLower(x_i, c, thm); // TODO: thm: = |- >=
02824   
02825   // Return the consistency
02826   return consistent;
02827 }
02828 
02829 
02830 void TheoryArithNew::checkSat(bool fullEffort)
02831 { 
02832   // We should not be here if inconsistent
02833   DebugAssert(consistent != UNSATISFIABLE, "TheoryArithNew::checkSat : we are UNSAT before entering?!?!");
02834 
02835   // Trace the check sat if simplex flag is on
02836     TRACE("simplex", "TheoryArithNew::checkSat(fullEffort=",fullEffort? "true" : "false", ")");
02837   
02838     // Check if by backtracking we have more fresh variables than we expect
02839   if (assertedExprCount < assertedExpr.size()) 
02840     updateFreshVariables();
02841   
02842     // Do the simplex search if the database is not satisfiable (if inconsistent, we will not be here);
02843     if (consistent != SATISFIABLE || fullEffort)
02844       consistent = checkSatSimplex();
02845             
02846     // If the result is inconsistent set the inconsistent flag
02847     if (consistent == UNSATISFIABLE)
02848       setInconsistent(explanation);
02849     
02850     // If we are not - consistent, check the integer satisfiability
02851 //    if (consistent == SATISFIABLE) {
02852 //    // If we asserted a lemma and it hasn't been processed yet, we just don't do anything
02853 //    Theorem integer_lemma_thm = integer_lemma;
02854 //    if (!integer_lemma_thm.isNull()) {
02855 //      if (simplify(integer_lemma_thm.getExpr()).getRHS() == getEM()->trueExpr())
02856 //        consistent = checkSatInteger();
02857 //      else 
02858 //        consistent = UNKNOWN;
02859 //    } else
02860 //      // Lemma was not asserted, check integer sat
02861 //      consistent = checkSatInteger();   
02862 //    }
02863     
02864     // Trace the check sat if simplex flag is on
02865     TRACE("simplex", "TheoryArithNew::checkSat ==> ", consistent == UNSATISFIABLE? "UNSATISFIABLE" : "SATISFIABLE", "");
02866 }
02867 
02868 QueryResult TheoryArithNew::checkSatInteger() {
02869   
02870   // Trace the check sat if simplex flag is on
02871     TRACE("simplex", "TheoryArithNew::checkSatInteger()", "", "");
02872     
02873     // At this point we are REAL satisfiable, so we have to check the integers
02874   set<Expr>::iterator x_i_it     = intVariables.begin();
02875   set<Expr>::iterator x_i_it_end = intVariables.end();
02876 //  cerr << "Integer vars: ";
02877 //  while (x_i_it != x_i_it_end) {
02878 //    cerr << *x_i_it << " ";
02879 //    ++ x_i_it;
02880 //  }
02881 //  cerr << endl;
02882 //  
02883 //  x_i_it     = intVariables.begin();
02884 //  x_i_it_end = intVariables.end();
02885   while (x_i_it != x_i_it_end) {
02886     
02887     // Get the left-hand variable of the tableaux
02888     const Expr& x_i = (*x_i_it);
02889     
02890     // Only do work for unsat integer variables
02891     if (isInteger(x_i)) {
02892       
02893       // Get the current assignment of x_i
02894       const EpsRational& beta = getBeta(x_i);
02895       
02896       // Check if it is an integer
02897       if (beta.isInteger()) { ++ x_i_it; continue; }
02898       
02899       // Since the variable is not an integer, split on it being <= [beta] and >= [beta] + 1
02900       integer_lemma = d_rules->integerSplit(x_i, beta.getFloor()); 
02901       TRACE("integer", "TheoryArithNew::checkSatInteger ==> lemma : ", integer_lemma, "");
02902       enqueueFact(integer_lemma);
02903       
02904       // One split should be enough, return unknown
02905       return UNKNOWN;      
02906     }
02907     
02908     // Go to the next row
02909     ++ x_i_it;
02910   } 
02911   
02912   // We came through, huh, we are sat
02913   return SATISFIABLE; 
02914 }
02915 
02916 QueryResult TheoryArithNew::checkSatSimplex() {
02917   
02918   Expr x_i;                         // The basic variable we will use
02919   EpsRational x_i_Value;            // The current value of the variable x_i
02920   Expr x_j;                         // The non-basic variable we will use
02921   EpsRational x_j_Value;            // The current value of the variable x_j
02922   Rational a_ij;                    // The coefficient wwhen expanding x_i using x_j in the tableaux
02923   
02924   bool x_j_Found;                   // Did we find a suitable one
02925   EpsRational l_i;                  // Lower bound of x_i
02926   EpsRational u_i;                  // Upper bound of x_i
02927 
02928   // Trace the size of the tableaux and the unsat 
02929     TRACE("arith_atoms", "Tableaux size: ", tableaux.size(), "");
02930   TRACE("arith_atoms", "UNSAT vars: ", unsatBasicVariables.size(), "");
02931   
02932   // The main loop
02933   while (unsatBasicVariables.size()) {
02934    
02935     // The first unsat variable information
02936     x_i        = *unsatBasicVariables.begin();
02937     TebleauxMap::iterator it = tableaux.find(x_i); 
02938     x_i_Value  = getBeta(x_i);
02939     l_i        = getLowerBound(x_i);
02940     u_i        = getUpperBound(x_i);
02941     
02942     // If the variable doesn't obey the lower bound 
02943     if (l_i > x_i_Value) {
02944       
02945       // Did we find a suitable x_j, NOT YET
02946       x_j_Found = false; 
02947           
02948       // Find the smalles non-basic x_j that can improve x_i
02949       const Expr& x_i_RightSide = (*it).second.getExpr()[1];
02950       int non_basics_i_end     = x_i_RightSide.arity();
02951       for(int non_basics_i = 0; non_basics_i < non_basics_i_end; ++ non_basics_i) {
02952         
02953         // Get the info on the current variable
02954         x_j        = x_i_RightSide[non_basics_i][1]; 
02955         a_ij       = x_i_RightSide[non_basics_i][0].getRational(); 
02956         x_j_Value  = getBeta(x_j);           
02957         
02958         // If there is slack for improving x_i using x_j then do it               
02959         if (a_ij > 0) {
02960           if (x_j_Value < getUpperBound(x_j)) {
02961             x_j_Found = true;
02962             break;
02963           }
02964         } else {
02965           if (x_j_Value > getLowerBound(x_j)) {
02966             x_j_Found = true;
02967             break;
02968           }
02969         }     
02970       }
02971       
02972       // If none of the variables allows for slack, the tableaux is unsatisfiable
02973       if (!x_j_Found) {
02974         // Generate the explanation
02975         explanation = getLowerBoundExplanation(it);
02976         // Return unsat
02977         return UNSATISFIABLE;
02978       }
02979       
02980       // Otherwise do pivotAndUpdate and continue with the loop
02981       pivotAndUpdate(x_i, x_j, l_i);       
02982     } else
02983     // If the variable doesn't obey the upper bound 
02984     if (x_i_Value > u_i) {
02985       
02986       // Did we find a suitable x_j, NOT YET
02987       x_j_Found = false; 
02988           
02989       // Find the smalles non-basic x_j that can improve x_i
02990       const Expr& x_i_RightSide = (*it).second.getExpr()[1];
02991       int non_basics_i_end     = x_i_RightSide.arity();
02992       for(int non_basics_i = 0; non_basics_i < non_basics_i_end; ++ non_basics_i) {
02993         
02994         // Get the info on the current variable
02995         x_j        = x_i_RightSide[non_basics_i][1]; 
02996         a_ij       = x_i_RightSide[non_basics_i][0].getRational(); 
02997         x_j_Value  = getBeta(x_j);           
02998         
02999         // If there is slack for improving x_i using x_j then do it
03000         if (a_ij < 0) {
03001           if (x_j_Value < getUpperBound(x_j)) {
03002             x_j_Found = true;
03003             break;
03004           }
03005         } else 
03006           if (x_j_Value > getLowerBound(x_j)) {
03007             x_j_Found = true;
03008             break;
03009           }     
03010       }
03011       
03012       // If none of the variables allows for slack, the tableaux is unsatisfiable
03013       if (!x_j_Found) {
03014         // Generate the explanation
03015         explanation = getUpperBoundExplanation(it);
03016         // Return unsat
03017         return UNSATISFIABLE; 
03018       }
03019       
03020       // Otherwise do pivotAndUpdate and continue with the loop
03021       pivotAndUpdate(x_i, x_j, u_i);       
03022     } else
03023       // Due to backtracking a unsat might become sat, just erase it
03024       unsatBasicVariables.erase(x_i);
03025       
03026     
03027     // If trace is on, printout the current valuation and the tableaux
03028     TRACE("simplex", "TheoryArithNew::checkSatSimplex ==> new tableaux : \n", tableauxAsString(), "");
03029     TRACE("simplex", "TheoryArithNew::checkSatSimplex ==> new bounds   : \n", boundsAsString(), "");
03030     TRACE("simplex", "TheoryArithNew::checkSatSimplex ==> unsat   : \n", unsatAsString(), "");
03031     
03032   };
03033 
03034   // Since there is no more unsat constraints we are satisfiable
03035   return SATISFIABLE;
03036 }     
03037 
03038 Rational TheoryArithNew::getTableauxEntry(const Expr& x_i, const Expr& x_j) {
03039   return findCoefficient(x_j, tableaux[x_i].getExpr()[1]);
03040 }
03041 
03042 
03043 const Rational& TheoryArithNew::findCoefficient(const Expr& var, const Expr& expr) {
03044 
03045   // The zero coefficient 
03046   static Rational zeroCoefficient(0);
03047 
03048     // The given expression must be a sum
03049     DebugAssert(isPlus(expr), "TheoryArithNew::findCoefficient : expression must be a sum : " + expr.toString());
03050   
03051   // Go through the sum and find the coefficient
03052   int left = 0;
03053   int right = expr.arity() - 1;
03054   int i;
03055   while (left <= right) {
03056     
03057     // Take the middle one
03058     i = (left + right ) / 2;
03059     
03060     // Current expression
03061     const Expr& mult = expr[i];
03062     
03063     // Every summand must be a multiplication with a rational
03064     DebugAssert(isMult(mult) && isRational(mult[0]), "TheoryArithNew::findCoefficient : expression must be a sum of multiplications: " + expr.toString()); 
03065     
03066     // If the variable is the same return the coefficient
03067     int cmp = compare(mult[1], var);
03068     if (cmp == 0) 
03069       return mult[0].getRational();
03070     else 
03071       if (cmp > 0) 
03072         left = i + 1;
03073       else 
03074         right = i - 1;    
03075   }
03076     
03077   // Not found, return 0
03078   return zeroCoefficient; 
03079 }
03080 
03081 
03082 TheoryArithNew::EpsRational TheoryArithNew::getLowerBound(const Expr& x) const {
03083   // Try and find the lower bound in the map
03084   CDMap<Expr, BoundInfo>::iterator find = lowerBound.find(x);
03085   // If not found return +infinity as the default value, othervise return the value
03086   if (find == lowerBound.end()) return EpsRational::MinusInfinity;
03087   else return (*find).second.bound;
03088 }
03089 
03090 TheoryArithNew::EpsRational TheoryArithNew::getUpperBound(const Expr& x) const {
03091   // Try and find the upper bound in the map
03092   CDMap<Expr, BoundInfo>::iterator find = upperBound.find(x);
03093   // If not found return -infinity as the default value, othervise return the value
03094   if (find == upperBound.end()) return EpsRational::PlusInfinity;
03095   else return (*find).second.bound;
03096 }
03097 
03098 Theorem TheoryArithNew::getLowerBoundThm(const Expr& x) const {
03099   // Try and find the upper bound in the map
03100   CDMap<Expr, BoundInfo>::iterator find = lowerBound.find(x);
03101   // It has to be found
03102   DebugAssert(find != lowerBound.end(), "TheoryArithNew::getLowerBoundThm, theorem not found for " + x.toString()); 
03103   // Return the bound theorem 
03104   return (*find).second.theorem;
03105 }
03106 
03107 Theorem TheoryArithNew::getUpperBoundThm(const Expr& x) const {
03108   // Try and find the upper bound in the map
03109   CDMap<Expr, BoundInfo>::iterator find = upperBound.find(x);
03110   // It has to be found
03111   DebugAssert(find != upperBound.end(), "TheoryArithNew::getUpperBoundThm, theorem not found for " + x.toString()); 
03112   // Return the bound theorem 
03113   return (*find).second.theorem;
03114 }
03115 
03116       
03117 TheoryArithNew::EpsRational TheoryArithNew::getBeta(const Expr& x) {
03118   
03119   // Try to find the beta value in the map
03120   CDMap<Expr, EpsRational>::iterator find = beta.find(x);
03121   
03122   if (find == beta.end()) {
03123     // If not found return 0 (no need for sat/unsat, it's allways sat) 
03124     return beta[x] = EpsRational::Zero;
03125   
03126     // Check if the variable is sat or unsat under the new assignment 
03127     if (EpsRational::Zero < getLowerBound(x) || getUpperBound(x) < EpsRational::Zero)
03128       unsatBasicVariables.insert(x);
03129     else
03130       unsatBasicVariables.erase(x);
03131   }
03132   else 
03133     // If found, just return it
03134     return (*find).second;
03135 }
03136 
03137 
03138 void TheoryArithNew::assertFact(const Theorem& assertThm)
03139 {
03140   // Get the expression to be asserted
03141   const Expr& expr = assertThm.getExpr();
03142 
03143   // If tracing arithmetic, print out the expression to be asserted
03144   TRACE("simplex", "TheoryArithNew::assertFact(", expr, ")");
03145   TRACE("simplex", "asserted: ", assertedExpr.size(), "");
03146   TRACE("simplex", "counted: ", assertedExprCount, "");
03147   TRACE("arith_atoms", "Assert: ", expr.toString(), "");
03148             
03149   // Check if by backtracking we have more fresh variables than we expect
03150   if (assertedExprCount < assertedExpr.size()) 
03151     updateFreshVariables();
03152   
03153   // Get the constraint partsreturn 
03154   const Expr& leftSide   = expr[0];          // The left side of the constraint  
03155   const Expr& rightSide  = expr[1];          // The right side of the constraint
03156   int kind        = expr.getKind();   // The relational symbol, should be one of LT, LE, GT, GE. EQ was rewritten as LE and GE so its not here
03157   
03158   // The expression must be an inequality (sum a_1*x_1 .. a_n*x_n) @ b
03159   DebugAssert(isIneq(expr)         , "TheoryArithNew::assertFact wrong kind, expected inequality"                 + expr.toString());
03160   DebugAssert(isPlus(rightSide) || (isMult(rightSide) && isRational(rightSide[0]) && isLeaf(rightSide[1])), "TheoryArithNew::assertFact wrong kind, expected sum on the right side opr a simple 1*x"      + expr.toString());
03161   DebugAssert(isRational(leftSide), "TheoryArithNew::assertFact wrong kind, expected rational on the right side" + expr.toString());
03162 
03163   // Get the rational value on the right side 
03164   Rational leftSideValue = leftSide.getRational(); 
03165   
03166   // The rational bound on the constraint
03167   Rational c = leftSideValue;
03168   
03169   // The variable to be constrained
03170   Expr var;       
03171   
03172   // Theorem of the assertion
03173   Theorem assert = assertThm;                                 
03174   
03175   // For now we have that leftSide @ (c1x1 + c2x2 + ... cnxn) = rightSide
03176   // If rightSide is not a sum constraint is atomic (leftSide @ a*x)
03177   if (!isPlus(rightSide)) {
03178     
03179     // Tee left side in this case should be 1*x
03180     DebugAssert(rightSide[0].isRational() && rightSide[0].getRational() == 1, "TheoryArithNew::assertFact, left side should be multiplication by one");
03181     
03182     // Change the assert theorem to remove the 1*x to x
03183     assert = iffMP(assert, substitutivityRule(expr, reflexivityRule(leftSide), d_rules->oneElimination(rightSide)));
03184     
03185     // The variable will just be x1 (if var is not already present in the tableaux, it will be non-basic)
03186     var = rightSide[1]; // IMPORTANT!!!, when giving explanations, it should be of the same form
03187     
03188     // If an integer, add it to the integer set
03189     if (isInteger(var)) intVariables.insert(var);
03190           
03191   } else {
03192     // Get the theorem that corresponds to the introduction of the new variable var = leftSide 
03193     const Theorem& introductionThm = getVariableIntroThm(rightSide);
03194     
03195     // Take the new variable out
03196     var = introductionThm.getExpr()[0];
03197 
03198     // Change the theorem for the assertion so that it involves the new variable, i.e.  c < rightSide, var = rightSide |- c < var
03199     assert = iffMP(assertThm, substitutivityRule(expr, 1, symmetryRule(introductionThm)));
03200     
03201     // Insert all the integer variables into the integer set
03202     if (isInteger(var)) {
03203       intVariables.insert(var);
03204       int i_end = rightSide.arity();
03205       for(int i = 0; i < i_end; ++ i)
03206         intVariables.insert(rightSide[i][1]);
03207     } else {
03208       int i_end = rightSide.arity();
03209       for(int i = 0; i < i_end; ++ i)
03210         if (isInteger(rightSide[i][1])) intVariables.insert(rightSide[i][1]);
03211     }
03212   }
03213   
03214   // Make the BoundInfo object for theory propagation
03215   EpsRational bound;
03216   
03217   // By default we don't propagate
03218   propagate = false;
03219   
03220   // Remember the old bound
03221   EpsRational oldBound;
03222   
03223   // Finnaly assert the right constraint
03224   switch (kind) {
03225     case LT: 
03226       oldBound    = getLowerBound(var);
03227       // c < var, convert to c + epsilon <= var and assert it
03228       consistent = assertLower(var, bound = EpsRational(c, +1), assert);
03229       break;          
03230     case LE:
03231       oldBound    = getLowerBound(var);
03232       // c <= var, assert the lower bound
03233       consistent = assertLower(var, bound = c, assert);
03234       break;
03235     case GT: 
03236       oldBound    = getUpperBound(var);
03237       // c > var, convert to c - epsilon >= var and assert it
03238       consistent = assertUpper(var, bound = EpsRational(c, -1), assert);
03239       break;
03240     case GE:
03241       oldBound    = getUpperBound(var);
03242       // c >= var, assert the upper bound
03243       consistent = assertUpper(var, bound = c, assert);
03244       break;
03245     case EQ:
03246       // c == var, assert the equality
03247       consistent = assertEqual(var, bound = c, assert);
03248       // For now, don't propagate anything
03249       propagate = false; // TODO: some propagation is in place here (negations)     
03250       break;
03251     default:
03252       //How did we get here
03253           FatalAssert(false, "Theory_Arith::assertFact, control should not reach here");
03254           break;
03255   } 
03256   
03257   // If tracing arithmetic, print out the new tableaux and the current bounds
03258   TRACE("simplex", "TheoryArithNew::assertFact ==> ", consistent == UNSATISFIABLE? "UNSATISFIABLE" : consistent == UNKNOWN? "UNKNOWN" : "SATISFIABLE", "");
03259   TRACE("simplex", "TheoryArithNew::assertFact ==> new tableaux : \n", tableauxAsString(), "");
03260   TRACE("simplex", "TheoryArithNew::assertFact ==> new bounds   : \n", boundsAsString(), "");
03261   TRACE("simplex", "TheoryArithNew::assertFact ==> unsat   : \n", unsatAsString(), "");
03262   
03263   // If the result is inconsistent set the inconsistent flag
03264     if (consistent == UNSATISFIABLE)
03265       setInconsistent(explanation);
03266       
03267     // Not inconsistent, propagate all from this assertion
03268     if (propagate) 
03269       propagateTheory(assertThm.getExpr(), bound, oldBound);    
03270 }
03271 
03272 
03273 Theorem TheoryArithNew::getVariableIntroThm(const Expr& rightSide) {
03274   
03275   // Try to find the expression in the map
03276   TebleauxMap::iterator find = freshVariables.find(rightSide);
03277   
03278   // If not in tableaux, add it and assign it a new variable
03279   if (find == freshVariables.end()) {
03280   
03281     // Get the common rules
03282     CommonProofRules* c_rules = getCommonRules();
03283   
03284     // Create a new variable (\exists x . rightSide = x)
03285     Theorem thm = c_rules->varIntroRule(rightSide);
03286       
03287       // Skolemise it, to get an equality (\exists x . rightSide = x) <==> rightSide = c, then infer |- rightSide = c
03288       thm = c_rules->iffMP(thm, c_rules->skolemizeRewrite(thm.getExpr()));    
03289       
03290       // Reverse the equality into standard form
03291       thm = symmetryRule(thm);
03292       
03293       // Add the theorem to the variable introduction map (this is the theorem we return)
03294       Theorem returnThm = freshVariables[rightSide] = thm;
03295       
03296       // Now, flatten the equality modulo tableaux
03297       thm = substAndCanonizeModTableaux(thm);
03298       
03299       // Get the skolem constant that was introduced (|- c = leftSide)
03300       const Expr& var = thm.getExpr()[0];
03301             
03302       // Also add it to the tableaux
03303       tableaux[var] = thm;
03304 
03305     // Update the dependencies
03306     updateDependenciesAdd(var, thm.getExpr()[1]);
03307 
03308     // Add it to the expressions map
03309     assertedExpr.push_back(Expr(EQ, var, rightSide));
03310     assertedExprCount = assertedExprCount + 1;
03311       
03312       // Compute the value of the new variable using the tableaux
03313     updateValue(var, rightSide);
03314             
03315       // Return the variable
03316       return returnThm;
03317   }
03318   
03319   // Otherwise we have it, so return it
03320   return (*find).second;
03321 }
03322 
03323 void TheoryArithNew::updateValue(const Expr& var, const Expr& e) {
03324   
03325     // The initial value
03326     EpsRational varValue(0);
03327     
03328     // Go through the sum and compute the value
03329     int i_end = e.arity();
03330     for (int i = 0; i < i_end; ++ i)
03331       varValue += getBeta(e[i][1]) * e[i][0].getRational();
03332     
03333     // Update the beta  
03334     beta[var] = varValue;
03335     
03336     // Check if the variable is sat or unsat under the new assignment 
03337   if (varValue < getLowerBound(var) || getUpperBound(var) < varValue)
03338     unsatBasicVariables.insert(var);
03339   else
03340     unsatBasicVariables.erase(var);
03341 }
03342 
03343 string TheoryArithNew::tableauxAsString() const {
03344 
03345   // The string we are building 
03346   string str; 
03347 
03348   // Start from the begining
03349   TebleauxMap::const_iterator row     = tableaux.begin();
03350   TebleauxMap::const_iterator row_end = tableaux.end(); 
03351   
03352   // Print all the rows
03353   while (row != tableaux.end()) {
03354     // Print the equality
03355     str = str + ((*row).second).getExpr().toString() + "\n";
03356     
03357     // Continue to the next row
03358     row ++;
03359   }
03360   
03361   // Return the string representation 
03362   return str;
03363 }
03364 
03365 string TheoryArithNew::unsatAsString() const {
03366 
03367   // The string we are building 
03368   string str; 
03369 
03370   // Start from the begining
03371   set<Expr>::const_iterator it     = unsatBasicVariables.begin();
03372   set<Expr>::const_iterator it_end = unsatBasicVariables.end(); 
03373   
03374   // Print all the rows
03375   while (it != it_end) {
03376     // Print the equality
03377     str = str + (*it).toString() + " ";
03378     
03379     // Continue to the next row
03380     it ++;
03381   }
03382   
03383   // Return the string representation 
03384   return str;
03385 }
03386 
03387 
03388 string TheoryArithNew::boundsAsString() {
03389 
03390   // The string we are building 
03391   string str; 
03392 
03393   // Set containing all the variables
03394   set<Expr> all_variables;
03395   
03396   // Go throught the tableaux and pick up all the variables
03397   TebleauxMap::const_iterator it     = tableaux.begin();
03398   TebleauxMap::const_iterator it_end = tableaux.end();
03399   for(; it != it_end; it ++) {
03400   
03401     // Add the basic variable to the set
03402     all_variables.insert((*it).first);
03403     
03404     // Go through all the expression variables and add them to the set
03405     const Expr& rightSide = (*it).second.getExpr()[1];
03406     int term_i_end = rightSide.arity();
03407     for(int term_i = 0; term_i < term_i_end; ++ term_i)
03408       all_variables.insert(rightSide[term_i][1]); 
03409   } 
03410   
03411   // Go throught the bounds map and pickup all the variables
03412   CDMap<Expr, BoundInfo>::iterator bounds_it;
03413   for (bounds_it = lowerBound.begin(); bounds_it != lowerBound.end(); bounds_it ++)
03414     all_variables.insert((*bounds_it).first);
03415   for (bounds_it = upperBound.begin(); bounds_it != upperBound.end(); bounds_it ++)
03416     all_variables.insert((*bounds_it).first);
03417     
03418   // Start from the begining
03419   set<Expr>::iterator var_it     = all_variables.begin();
03420   set<Expr>::iterator var_it_end = all_variables.end(); 
03421   
03422   // Print all the rows
03423   while (var_it != var_it_end) {
03424     
03425     // The current variable
03426     const Expr& var = *var_it;
03427     
03428     // Print the equality
03429     str += getLowerBound(var).toString() + " <= " + var.toString() + "(" + getBeta(var).toString() + ") <= " + getUpperBound(var).toString() + "\n";
03430       
03431     // Continue to the next variable
03432     var_it ++;
03433   }
03434   
03435   // Return the string representation 
03436   return str;
03437 }
03438 
03439 // The infinity constant 
03440 const TheoryArithNew::EpsRational TheoryArithNew::EpsRational::PlusInfinity(PLUS_INFINITY);
03441 // The negative infinity constant
03442 const TheoryArithNew::EpsRational TheoryArithNew::EpsRational::MinusInfinity(MINUS_INFINITY);
03443 // The negative infinity constant
03444 const TheoryArithNew::EpsRational TheoryArithNew::EpsRational::Zero;
03445 
03446 
03447 Theorem TheoryArithNew::substAndCanonizeModTableaux(const Theorem& eq) {
03448 
03449   // If subst is empty, just return
03450     if(tableaux.empty()) return eq;
03451 
03452   // Get the expression of the equality
03453   const Expr& eqExpr = eq.getExpr();
03454 
03455   // Check if the equality if in the canonic form
03456   DebugAssert(eqExpr.getKind() == EQ, "TheoryArithNew::substAndCanonize, expected equality " + eqExpr.toString());
03457   
03458   // Get the left side of the equality
03459   const Expr& rightSide = eqExpr[1];
03460 
03461     // Do the actual substitution in the eqExpr
03462     Theorem thm = substAndCanonizeModTableaux(rightSide);
03463   
03464     // If the substitution had no result just return the original equation
03465     if(thm.getRHS() == rightSide) return eq;
03466     
03467     // Return the theorem 
03468     return iffMP(eq, substitutivityRule(eq.getExpr(), 1, thm));
03469 }
03470 
03471 Theorem TheoryArithNew::substAndCanonizeModTableaux(const Expr& sum) {
03472     
03473     Theorem res;                      // The resulting theorem    
03474     vector<Theorem> thms;             // The theorems of the changed terms for the substitution
03475     vector<unsigned> changed;         // The indices of the changed terms for the substitution
03476   
03477   // Trace the canonisation
03478   TRACE("simplex", "TheoryArithNew::substAndCanonizeModTableaux(", sum, ")");
03479   
03480   // Check if the equality if in the canonic form
03481   DebugAssert(sum.getKind() == PLUS, "TheoryArithNew::substAndCanonize, expected sum " + sum.toString());
03482    
03483     // Go throught the sum and try to substitute the variables
03484     int term_index_end = sum.arity();
03485     for(int term_index = 0; term_index < term_index_end; ++ term_index) {
03486 
03487     const Expr& term = sum[term_index]; // The current term expression (a*x)
03488     const Expr& var  = term[1];         // The variable of the current term
03489   
03490       // Find the variable in the map
03491       TebleauxMap::iterator find = tableaux.find(var);
03492       
03493       // If found, substitute it
03494       if (find != tableaux.end()) {
03495         
03496         // Substitute the variable
03497         Theorem termTheorem = canonThm(substitutivityRule(term, 1, (*find).second));
03498         
03499         // Check that the result is not trivial 
03500         DebugAssert(termTheorem.getExpr() != term, "substAndCanonizeModTableaux: got the same term in substitution");
03501           
03502       // Push it to the theorems vector
03503           thms.push_back(termTheorem);
03504           
03505           // Add the index to the changed vector
03506           changed.push_back(term_index);      
03507       }     
03508     }
03509   
03510     // Do the actual substitution and canonize the result
03511     if(thms.size() > 0) {
03512       // Substitute the changed subterms into the term
03513       res = substitutivityRule(sum, changed, thms);
03514       // Canonise the result
03515       res = canonThm(res);
03516     } else
03517       // Nothing happened, just return the reflexivity
03518       res = reflexivityRule(sum);     
03519   
03520     // Return the result
03521     return res;
03522 }
03523 
03524 void TheoryArithNew::substAndCanonizeTableaux(const Theorem& eq) {
03525 
03526   Theorem result; // The explaining theorem
03527     
03528   // Trace 
03529   TRACE("simplex", "TheoryArithNew::substAndCanonizeTableaux(", eq.getExpr(), ")");
03530     
03531   // Get the expression of the equality
03532   const Expr& eqExpr = eq.getExpr();
03533 
03534   // Check if the equality if in the canonic form
03535   DebugAssert(eqExpr.getKind() == EQ, "TheoryArithNew::substAndCanonize, expected equality " + eqExpr.toString());
03536   
03537   // Get the variable of the substitution
03538   const Expr& var = eqExpr[0];
03539 
03540   // Check if there are variables that depend on x_j
03541   DependenciesMap::iterator find = dependenciesMap.find(var);
03542   if (find != dependenciesMap.end()) {
03543       
03544     // Go through all the variables that depend on x_j, and update their value
03545     set<Expr>& dependent = (*find).second;
03546     set<Expr>::iterator it     = dependent.begin();
03547     set<Expr>::iterator it_end = dependent.end();     
03548     for(; it != it_end; ++ it) {
03549       
03550       // Get the expression and the right side of the row from the tableaux
03551       const Expr& leftSide      = *it;
03552       TebleauxMap::iterator row = tableaux.find(leftSide);
03553       const Expr& rowExpr       = (*row).second.getExpr();
03554       const Expr& rowRightSide  = rowExpr[1];
03555       
03556       // Go through the sum and try to substitute
03557       int right = rowRightSide.arity() - 1;
03558       int left  = 0;
03559       int term_i;
03560       while (left <= right) { 
03561         
03562         // Get the middle one
03563         term_i = (left + right) / 2;
03564         
03565         // Get the comparison of the variables
03566         int cmp = compare(rowRightSide[term_i][1], var);
03567               
03568         // If the variable is found
03569         if (cmp == 0) {
03570           
03571           // Do the substitution and canonise
03572           result = canonThm(substitutivityRule(rowRightSide[term_i], 1, eq));
03573           // Do the substitution and canonise in the sum
03574           result = canonThm(substitutivityRule(rowRightSide, term_i, result));
03575           // Do the substitution
03576           result = substitutivityRule(rowExpr, 1, result);
03577           
03578           // Get the new expression
03579           const Expr& newRowRightSide = result.getRHS()[1];       
03580           // Update the dependencies of the varriables in the expression
03581           updateDependencies(rowRightSide, newRowRightSide, leftSide, var); 
03582           
03583           // That's it, remember the new row
03584           (*row).second = iffMP((*row).second, result);       
03585           
03586           // Variables don't repeat, we can just break out        
03587           break;
03588         } else if (cmp > 0) 
03589           left = term_i + 1;
03590         else 
03591           right = term_i - 1;
03592       }
03593     }
03594     
03595     // Now nobody depends on var anymore, just erase it
03596       dependent.clear();
03597   } 
03598 }
03599 
03600 Theorem TheoryArithNew::pivotRule(const Theorem& eq, const Expr& var) {
03601 
03602   Theorem result;  // The theorem explaining the result
03603 
03604   // Get the expression
03605   const Expr& eqExpr = eq.getExpr();
03606   const Expr& right_side = eqExpr[1];
03607   const Expr& left_side = eqExpr[0];
03608 
03609   // Trace if askedTheorem canonLeft  = d_rules->canonMult(thm.getExpr()[0]);
03610       
03611   TRACE("simplex", "TheoryArithNew::pivotRule(", eqExpr.toString() + ", ", var.toString() + ")"); 
03612 
03613   // Eq must be an equation with the sum on the left side and a leaf on the right side (variable)
03614   DebugAssert(eqExpr.getKind() == EQ, "TheoryArithNew::pivotRule, expected an equality : " + eqExpr.toString());
03615   DebugAssert(right_side.getKind() == PLUS, "TheoryArithNew::pivotRule, expected a sum on the left-hand side : " + eqExpr.toString());
03616   DebugAssert(isLeaf(left_side), "TheoryArithNew::pivotRule, expected a leaf (variable) on the right-hand side : " + eqExpr.toString());
03617 
03618   // Find the term of var in the left-hand side of eq
03619   int term_i_end = right_side.arity();
03620   for(int term_i = 0; term_i < term_i_end; ++ term_i)
03621     // If found do the stuff
03622     if (right_side[term_i][1] == var) {
03623   
03624       // This is the term we need and the rational we need
03625       const Expr& termExpr = right_side[term_i];
03626       const Expr& termVar = termExpr[1]; 
03627       const Rational& termRat = termExpr[0].getRational();
03628       
03629       // Construct the expression we will add to the equality
03630       const Expr& minusTermExpr = multExpr(rat(-termRat), termVar);
03631       const Expr& minusVarExpr  = multExpr(rat(-1), left_side); 
03632     
03633       // Add the above expressions to the to the equality
03634       result = iffMP(eq, d_rules->plusPredicate(left_side, right_side, plusExpr(minusTermExpr, minusVarExpr), EQ));
03635       // Canonise the right-hand side
03636       result = transitivityRule(result, canon(result.getExpr()[1]));
03637       // Canonise the left-hand side 
03638       result = transitivityRule(symmetryRule(canon(result.getExpr()[0])), result);
03639       // Multiply by the inverse of the rational constant (negated and ^-1)
03640       result = iffMP(result, d_rules->multEqn(result.getExpr()[0], result.getExpr()[1], rat(-1/termRat)));
03641       // Canonise the left-hand side
03642       result = transitivityRule(result, canon(result.getExpr()[1]));
03643       // Canonise the right=hand side 
03644       result = transitivityRule(symmetryRule(canon(result.getExpr()[0])), result);
03645       // Rewrite 1*x => x in the left-hand side
03646       result = transitivityRule(symmetryRule(d_rules->oneElimination(result.getExpr()[0])), result);
03647       
03648       // Trace the result
03649       TRACE("simplex", "TheoryArithNew::pivotRule ==> ", result.getExpr().toString(), "");
03650       
03651       // We are done, there is just one variable there
03652       return result;
03653     }
03654   
03655   // If not found, there is something wrong
03656   DebugAssert(false, "TheoryArithNew::pivotRule, " + var.toString() + " does not occur in " + eqExpr.toString());
03657 
03658   // Dummy return 
03659   return result;
03660 }
03661 
03662 Theorem TheoryArithNew::getLowerBoundExplanation(const TebleauxMap::iterator& var_it) {
03663 
03664   vector<Theorem> upperBounds; // Vector of the upper-bound theorems 
03665   
03666   // Get the tableaux theorem explaining the leftside = var
03667   Theorem tableauxTheorem = (*var_it).second;
03668   
03669   // Get the variable on the right side
03670   const Expr& var = (*var_it).first;
03671 
03672   // Get the expression involved (leftSide = var)
03673   const Expr& rightSide = tableauxTheorem.getExpr()[1];
03674   
03675   // Go through the left side and pick up the apropriate lower and upper bounds
03676   int leftSide_i_end = rightSide.arity();
03677   for(int leftSide_i = 0; leftSide_i < leftSide_i_end; ++ leftSide_i) {
03678 
03679     // Get the rational
03680     const Expr& a = rightSide[leftSide_i][0];
03681     
03682     // Get the variable
03683     const Expr& x = rightSide[leftSide_i][1];
03684     
03685     // The positive ones make up the upper bounds (x < u => a * x < a * u)
03686     if (a.getRational() > 0) {
03687       // Get the upper bound x < u
03688       Theorem thm = getUpperBoundThm(x);
03689       
03690       // Multiply if by a ==> u_i * a > x * a
03691       thm = iffMP(thm, d_rules->multIneqn(thm.getExpr(), a));
03692     
03693       // Canonise the left and the right side
03694       Theorem canonRight  = d_rules->canonMultTermConst(thm.getExpr()[1][1], thm.getExpr()[1][0]);
03695       Theorem canonLeft = d_rules->canonMultConstConst(thm.getExpr()[0][0], thm.getExpr()[0][1]); 
03696       
03697       // Substitute the canonised to the inequality
03698       thm = iffMP(thm, substitutivityRule(thm.getExpr(), canonLeft, canonRight));
03699       
03700       // Add the bound to the vector of upper bounds (|- c_x > a * x) 
03701       upperBounds.push_back(thm);
03702     } 
03703     // The negative ones make up the lower bounds (x > l => a * x < a * l)
03704     else {
03705       // Get the lower bound l < x
03706       Theorem thm = getLowerBoundThm(x);
03707       
03708       // Multiply if by a |- l * a < x * a  
03709       thm = iffMP(thm, d_rules->multIneqn(thm.getExpr(), a));
03710     
03711       // Canonise the left and the right side
03712       Theorem canonRight  = d_rules->canonMultTermConst(thm.getExpr()[1][1], thm.getExpr()[1][0]);
03713       Theorem canonLeft = d_rules->canonMultConstConst(thm.getExpr()[0][0], thm.getExpr()[0][1]); 
03714       
03715       // Substitute the canonised to the inequality
03716       thm = iffMP(thm, substitutivityRule(thm.getExpr(), canonLeft, canonRight));
03717       
03718       // Add the bound to the vector of upper bounds (|- c_x > a * x)
03719       upperBounds.push_back(thm);
03720     }
03721   } 
03722   
03723   // Add up all the inequalities to get a C = \sum c_i > rightSide 
03724   Theorem sumInequalities = upperBounds[0];
03725   for(unsigned int i = 1; i < upperBounds.size(); i ++) { 
03726     // Add the inequalities
03727     sumInequalities = d_rules->addInequalities(sumInequalities, upperBounds[i]);
03728     
03729     // Canonise the left and the right side
03730     Theorem canonLeft  = d_rules->canonPlus(sumInequalities.getExpr()[0]);
03731     Theorem canonRight = d_rules->canonPlus(sumInequalities.getExpr()[1]);
03732     
03733     // Substitute the canonised to the inequality
03734     sumInequalities = iffMP(sumInequalities, substitutivityRule(sumInequalities.getExpr(), canonLeft, canonRight));   
03735   }
03736   
03737   // Substitute to get C > rightSide ==> C > var
03738   Theorem varUpperBound = substitutivityRule(sumInequalities.getExpr(), 1, symmetryRule(tableauxTheorem));  
03739   // MP to get C > var
03740   varUpperBound = iffMP(sumInequalities, varUpperBound);
03741   
03742   // Get the lower bound on the rigth side variable (l_var < var)
03743   Theorem varLowerBound = getLowerBoundThm(var);
03744 
03745   // Return the clashing bound theorem 
03746   return d_rules->clashingBounds(varLowerBound, varUpperBound);
03747 }
03748 
03749 Theorem TheoryArithNew::getUpperBoundExplanation(const TebleauxMap::iterator& var_it) {
03750 
03751   vector<Theorem> lowerBounds; // Vector of the upper-bound theorems 
03752   
03753   // Get the tableaux theorem explaining the leftside = var
03754   Theorem tableauxTheorem = (*var_it).second;
03755   
03756   // Get the variable on the right side
03757   const Expr& var = (*var_it).first;
03758 
03759   // Get the expression involved (var = rightSide)
03760   const Expr& rightSide = tableauxTheorem.getExpr()[1];
03761   
03762   // Trace if requested
03763   TRACE("explanations", "Generating explanation for the tableaux row ", tableauxTheorem.getExpr(), "");
03764   
03765   // Go through the right side and pick up the apropriate lower and upper bounds
03766   int rightSide_i_end = rightSide.arity();
03767   for(int rightSide_i = 0; rightSide_i < rightSide_i_end; ++ rightSide_i) {
03768 
03769     // Get the rational
03770     const Expr& a = rightSide[rightSide_i][0];
03771     
03772     // Get the variable
03773     const Expr& x = rightSide[rightSide_i][1];
03774     
03775     // The positive ones make up the lower bounds (x > l => a * x > a * l)
03776     if (a.getRational() > 0) {
03777       // Get the lower bound l < x
03778       Theorem thm = getLowerBoundThm(x);
03779       TRACE("explanations", "Got ", thm.getExpr(), "");
03780       
03781       // Multiply if by a ==> l * a < x * a
03782       thm = iffMP(thm, d_rules->multIneqn(thm.getExpr(), a));
03783       TRACE("explanations", "Got ", thm.getExpr(), "");
03784     
03785       // Canonise the left and the right side
03786       Theorem canonRight  = d_rules->canonMultTermConst(thm.getExpr()[1][1], thm.getExpr()[1][0]);
03787       Theorem canonLeft = d_rules->canonMultConstConst(thm.getExpr()[0][0], thm.getExpr()[0][1]); 
03788       
03789       // Substitute the canonised to the inequality
03790       thm = iffMP(thm, substitutivityRule(thm.getExpr(), canonLeft, canonRight));
03791       TRACE("explanations", "Got ", thm.getExpr(), "");
03792       
03793       // Add the bound to the vector of upper bounds (|- c_x < a * x) 
03794       lowerBounds.push_back(thm);
03795     } 
03796     // The negative ones make up the upper bounds (x < u => a * x > a * u)
03797     else {
03798       // Get the upper bound u > x
03799       Theorem thm = getUpperBoundThm(x);
03800       TRACE("explanations", "Got ", thm.getExpr(), "");
03801     
03802       // Multiply it by a |- u * a > x * a 
03803       thm = iffMP(thm, d_rules->multIneqn(thm.getExpr(), a));
03804       TRACE("explanations", "Got ", thm.getExpr(), "");
03805     
03806       // Canonise the left and the right side
03807       Theorem canonRight = d_rules->canonMultTermConst(thm.getExpr()[1][1], thm.getExpr()[1][0]);
03808       Theorem canonLeft  = d_rules->canonMultConstConst(thm.getExpr()[0][0], thm.getExpr()[0][1]); 
03809       
03810       // Substitute the canonised to the inequality
03811       thm = iffMP(thm, substitutivityRule(thm.getExpr(), canonLeft, canonRight));
03812       TRACE("explanations", "Got ", thm.getExpr(), "");
03813       
03814       // Add the bound to the vector of upper bounds (|- c_x < a * x)
03815       lowerBounds.push_back(thm);
03816     }
03817   } 
03818   
03819   // Add up all the inequalities to get a \sum c_i = C > rightSide
03820   Theorem sumInequalities = lowerBounds[0];
03821   for(unsigned int i = 1; i < lowerBounds.size(); i ++) { 
03822     // Add the inequalities
03823     sumInequalities = d_rules->addInequalities(sumInequalities, lowerBounds[i]);
03824     
03825     TRACE("explanations", "Got sum ", sumInequalities.getExpr(), "");
03826     
03827     // Canonise the left and the right side
03828     Theorem canonLeft  = d_rules->canonPlus(sumInequalities.getExpr()[0]);
03829     Theorem canonRight = d_rules->canonPlus(sumInequalities.getExpr()[1]);
03830     
03831     // Substitute the canonised to the inequality
03832     sumInequalities = iffMP(sumInequalities, substitutivityRule(sumInequalities.getExpr(), canonLeft, canonRight));   
03833   }
03834   
03835   // Trace if requested
03836   TRACE("explanations", "Got sum ", sumInequalities.getExpr(), "");
03837 
03838   // Substitute to get C < leftSide ==> C < var
03839   Theorem varLowerBound = substitutivityRule(sumInequalities.getExpr(), 1, symmetryRule(tableauxTheorem));  
03840   
03841   // MP to get C < var
03842   varLowerBound = iffMP(sumInequalities, varLowerBound);
03843 
03844   // Trace if requested
03845   TRACE("explanations", "Got lower bound ", varLowerBound.getExpr(), "");
03846   
03847   // Get the lower bound on the rigth side variable (var > l_var)
03848   Theorem varUpperBound = getUpperBoundThm(var);
03849 
03850   // Trace if requested
03851   TRACE("explanations", "Got upper bound ", varUpperBound.getExpr(), "");
03852 
03853   TRACE("explanations", "The var value (", var, ")" + getBeta(var).toString());
03854 
03855   // Return the clashing bound theorem 
03856   return d_rules->clashingBounds(varLowerBound, varUpperBound);
03857 }
03858 
03859 void TheoryArithNew::updateFreshVariables() {
03860 
03861   unsigned int size = assertedExpr.size();
03862   unsigned int i;
03863 
03864   for (i = assertedExprCount; i < size; ++ i)
03865     //Update the value
03866     updateValue(assertedExpr[i][0], assertedExpr[i][1]);
03867 
03868   // Update the asserted count to be the size of the vector
03869   assertedExprCount = i;
03870 
03871 }
03872 
03873 void TheoryArithNew::updateDependenciesAdd(const Expr& var, const Expr& sum) {
03874   
03875   // Trace it
03876   TRACE("tableaux_dep", "updateDependenciesAdd(", var.toString() + ", ", sum.toString() + ")");
03877   
03878   // Go through the sum and add var to the dependencies of that term variable
03879   Expr::iterator term = sum.begin();
03880   Expr::iterator term_end = sum.end();
03881   for(; term != term_end; term ++)
03882     dependenciesMap[(*term)[1]].insert(var);
03883 
03884 }
03885 
03886 void TheoryArithNew::updateDependenciesRemove(const Expr& var, const Expr& sum) {
03887   
03888   // Trace it
03889   TRACE("tableaux_dep", "updateDependenciesRemove(", var.toString() + ", ", sum.toString() + ")");
03890     
03891   // Go through the sum and remove var to the dependencies of that term variable
03892   Expr::iterator term = sum.begin();
03893   Expr::iterator term_end = sum.end();
03894   for(; term != term_end; term ++)
03895     dependenciesMap[(*term)[1]].erase(var);
03896 
03897 }
03898 
03899 void TheoryArithNew::updateDependencies(const Expr& oldSum, const Expr& newSum, const Expr& dependentVar, const Expr& skipVar) {
03900 
03901   // Trace it
03902   TRACE("tableaux_dep", "updateDependencies(", oldSum.toString() + ", " + newSum.toString() + ", " + dependentVar.toString(), ")");
03903   
03904   // Since the sums are ordered by variables, we can just to a "merge sort"
03905   int oldSum_i = 0, newSum_i = 0;
03906   int oldSum_end = oldSum.arity(), newSum_end = newSum.arity();
03907   // Get the first variables
03908   while (oldSum_i < oldSum_end && newSum_i < newSum_end) {
03909     
03910     // Get the variable references
03911     const Expr oldVar = oldSum[oldSum_i][1];
03912     const Expr newVar = newSum[newSum_i][1];
03913     
03914     // If variables equal, just skip, everything is ok
03915     if (oldVar == newVar) {
03916       ++ oldSum_i; ++ newSum_i; continue; 
03917     } 
03918     
03919     // Otherwise do the work with the smaller one
03920     if (oldVar > newVar) {
03921       // Old variable has dissapeared, remove dependent from its list 
03922       if (oldVar != skipVar)
03923         dependenciesMap[oldVar].erase(dependentVar);
03924       // Move the old variable forward
03925       ++ oldSum_i; 
03926     } else { 
03927       // New variable has appeared, insert dependent to its list
03928       if (newVar != skipVar)
03929         dependenciesMap[newVar].insert(dependentVar);
03930       // Move the new variable forward
03931       ++ newSum_i;
03932     }
03933   } 
03934 
03935   // If there is leftovers in the old sum, just do the removals
03936   while (oldSum_i < oldSum_end) {
03937     // Get the var, and increase the index
03938     const Expr& var = oldSum[oldSum_i ++][1];
03939     // Update the dependency
03940     if (var != skipVar) 
03941       dependenciesMap[var].erase(dependentVar);
03942   }
03943   
03944   while (newSum_i < newSum_end) {
03945     // Get the var, and increase the index
03946     const Expr& var = newSum[newSum_i ++][1];
03947     // Update the dependency
03948     if (var != skipVar) 
03949       dependenciesMap[var].insert(dependentVar);
03950   }
03951 }
03952 
03953 void TheoryArithNew::registerAtom(const Expr& e) {
03954   
03955   // Trace it
03956   TRACE("propagate_arith", "registerAtom(", e.toString(), ")");
03957   TRACE("arith_atoms", "", e.toString(), "");
03958   
03959   // If it is a atomic formula, add it to the map 
03960   if (e.isAbsAtomicFormula()) {
03961     Expr rightSide    = e[1];
03962     int kind          = e.getKind();
03963     Rational leftSide = e[0].getRational();
03964     
03965     // The eps bound we'll be using
03966     EpsRational bound; 
03967     
03968     // Depending on the type of the inequality define the bound
03969     switch (kind) {
03970       case LT: 
03971         bound = EpsRational(leftSide, +1);
03972         break;          
03973       case LE:
03974         bound = leftSide;
03975         break;
03976       case GT: 
03977         bound = EpsRational(leftSide, -1);
03978         break;
03979       case GE:
03980         bound = leftSide;
03981         break;      
03982       default:
03983         // How did we get here
03984             FatalAssert(false, "TheoryArithNew::registerAtom: control should not reach here" + e.toString()); 
03985     }
03986     
03987     // Bound has been set, now add the
03988     allBounds.insert(ExprBoundInfo(bound, e));    
03989   } 
03990 
03991 //  // Printout the current set of atoms in the set
03992 //  cout << "ALL BOUNDS:" << endl;
03993 //  BoundInfoSet::iterator it = allBounds.begin();
03994 //  while (it != allBounds.end()) {
03995 //    cout << (*it).e << endl;
03996 //    ++ it;
03997 //  }
03998 }
03999 
04000 void TheoryArithNew::propagateTheory(const Expr& assertExpr, const EpsRational& bound, const EpsRational& oldBound) {
04001 
04002   // Trace it
04003   TRACE("propagate_arith", "propagateTheory(", assertExpr.toString() + ", " + bound.toString(), ")");
04004 
04005   // Make the bound info object, so that we can search for it
04006   ExprBoundInfo boundInfo(bound, assertExpr);
04007   
04008     // Get the exression on the right side hand
04009   Expr rightSide = assertExpr[1];
04010   
04011   // Get the kid of the disequality
04012   int kind = assertExpr.getKind();
04013   
04014   // Check wheather the kind is one of LT, LE, GT, GE
04015   DebugAssert(kind == LT || kind == LE || kind == GT || kind == GE , "TheoryArithNew::propagateTheory : expected an inequality");
04016   
04017   // If the bound is of the type LT or LE we go up
04018   if (kind == LT || kind == LE) {
04019     // Find the asserted fact in the set (it must be there)
04020     BoundInfoSet::iterator find      = allBounds.lower_bound(boundInfo);
04021     BoundInfoSet::iterator find_end  = allBounds.lower_bound(ExprBoundInfo(oldBound, assertExpr));
04022     
04023     // If we are at the begining, or not found, just exit
04024     if (find == find_end) return;
04025     
04026     // Now, go up until reached wrong right side (skip the first one, its the same as given)
04027     while (find != find_end) {
04028       
04029       // Go up;
04030       -- find;
04031     
04032       // Get the theorem of the find
04033       const Expr& findExpr = (*find).e;
04034       
04035       // Get the bound of the find
04036       const EpsRational findRat = (*find).bound; 
04037     
04038       // Get the kind of the expression in the theorem
04039       int findExprKind = findExpr.getKind();
04040       
04041       // Check if the right sides are the same
04042       if (rightSide != findExpr[1]) break;
04043     
04044       // Construct the theorem object
04045       Theorem lemma;
04046     
04047       // Check the type and equeue the lemma 
04048       if (findExprKind == LT || findExprKind == LE)
04049         // Imply the weaker inequality
04050         lemma = d_rules->implyWeakerInequality(assertExpr, findExpr);
04051       else
04052         // Imply the negation of the impossible inequality
04053         lemma = d_rules->implyNegatedInequality(assertExpr, findExpr);
04054         
04055     
04056       TRACE("propagate_arith", "lemma ==>", lemma.toString(), "");
04057       TRACE("arith_atoms", "Propagate: ", lemma.getExpr().toString(), "");
04058     
04059       // Put it across
04060       enqueueFact(lemma);
04061     }
04062   }  
04063   // If the bound is of the type GT or GE we go down
04064   else {
04065     // Find the asserted fact in the set (it must be there)
04066     BoundInfoSet::iterator find          = allBounds.upper_bound(boundInfo);
04067     BoundInfoSet::iterator find_end      = allBounds.upper_bound(ExprBoundInfo(oldBound, assertExpr));
04068     
04069     // Now, go down until reached wrong right side (skip the first one, its the same as given)
04070     while (find != find_end) {
04071               
04072       // Get the bound of the find
04073       const EpsRational findRat = (*find).bound; 
04074     
04075       // Get the expression in the theorem
04076       const Expr& findExpr = (*find).e;
04077       int findExprKind = findExpr.getKind();
04078       
04079       // Check if the right sides are the same
04080       if (rightSide != findExpr[1]) break;
04081     
04082       // Construct the theorem object
04083       Theorem lemma;
04084     
04085       // Check the type and equeue the lemma 
04086       if (findExprKind == GT || findExprKind == GE)
04087         // Imply the weaker inequality
04088         lemma = d_rules->implyWeakerInequality(assertExpr, findExpr);
04089       else
04090         // Imply the negation of the impossible inequality (use oposite than above)
04091         lemma = d_rules->implyNegatedInequality(assertExpr, findExpr);
04092             
04093       TRACE("propagate_arith", "lemma ==>", lemma.toString(), "");
04094       TRACE("arith_atoms", "Propagate: ", lemma.getExpr().toString(), "");
04095         
04096       // Put it across
04097       enqueueFact(lemma);
04098       
04099       // Go to the next one
04100       ++ find;
04101     }
04102   } 
04103 }
04104 
04105 Theorem TheoryArithNew::deriveGomoryCut(const Expr& x_i) {
04106 
04107   Theorem res;
04108 
04109   // CHECK IF APPLICABLE
04110   DebugAssert(isBasic(x_i), "TheoryArithNew::deriveGomoryCut variable must be a basic variable : " + x_i.toString()); 
04111   DebugAssert(intVariables.count(x_i) > 0, "TheoryArithNew::deriveGomoryCut variable must be a basic variable : " + x_i.toString());
04112 
04113   // Get the rational value of x_i
04114   Rational x_i_Value = getBeta(x_i).getRational();
04115   
04116   // Compute f_0
04117   Rational f_0 = x_i_Value - floor(x_i_Value);
04118     
04119   return res;
04120 }