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       switch(e.getKind()) {
02387         case REAL_CONST:
02388           printRational(os, e[0].getRational(), true);
02389           break;
02390         case RATIONAL_EXPR:
02391           printRational(os, e.getRational());
02392           break;
02393         case REAL:
02394           os << "Real";
02395           break;
02396         case INT:
02397           os << "Int";
02398           break;
02399         case SUBRANGE:
02400           throw SmtlibException("TheoryArithNew::print: SMTLIB: SUBRANGE not implemented");
02401 //           if(e.arity() != 2) e.print(os);
02402 //           else 
02403 //             os << "(" << push << "SUBRANGE" << space << e[0]
02404 //         << space << e[1] << push << ")";
02405           break;
02406         case IS_INTEGER:
02407     if(e.arity() == 1)
02408       os << "(" << push << "IsInt" << space << e[0] << push << ")";
02409     else
02410             throw SmtlibException("TheoryArithNew::print: SMTLIB: IS_INTEGER used unexpectedly");
02411     break;
02412         case PLUS:  {
02413           os << "(" << push << "+";
02414           Expr::iterator i = e.begin(), iend = e.end();
02415           for(; i!=iend; ++i) {
02416             os << space << (*i);
02417           }
02418           os << push << ")";
02419           break;
02420         }
02421         case MINUS: {
02422           os << "(" << push << "- " << e[0] << space << e[1] << push << ")";
02423           break;
02424         }
02425         case UMINUS: {
02426           os << "(" << push << "-" << space << e[0] << push << ")";
02427           break;
02428         }
02429         case MULT:  {
02430           int i=0, iend=e.arity();
02431           for(; i!=iend; ++i) {
02432             if (i < iend-1) {
02433               os << "(" << push << "*";
02434             }
02435             os << space << e[i];
02436           }
02437           for (i=0; i < iend-1; ++i) os << push << ")";
02438           break;
02439         }
02440         case POW:
02441           throw SmtlibException("TheoryArithNew::print: SMTLIB: POW not supported");
02442           //          os << "(" << push << "^ " << e[1] << space << e[0] << push << ")";
02443           break;
02444         case DIVIDE: {
02445           throw SmtlibException("TheoryArithNew::print: SMTLIB: unexpected use of DIVIDE");
02446           break;
02447         }
02448         case LT: {
02449           Rational r;
02450           os << "(" << push << "<" << space;
02451           os << e[0] << space << e[1] << push << ")";
02452           break;
02453         }
02454         case LE: {
02455           Rational r;
02456           os << "(" << push << "<=" << space;
02457           os << e[0] << space << e[1] << push << ")";
02458           break;
02459         }
02460         case GT: {
02461           Rational r;
02462           os << "(" << push << ">" << space;
02463           os << e[0] << space << e[1] << push << ")";
02464           break;
02465         }
02466         case GE: {
02467           Rational r;
02468           os << "(" << push << ">=" << space;
02469           os << e[0] << space << e[1] << push << ")";
02470           break;
02471         }
02472         case DARK_SHADOW:
02473           throw SmtlibException("TheoryArithNew::print: SMTLIB: DARK_SHADOW not supported");
02474     os << "(" << push << "DARK_SHADOW" << space << e[0]
02475        << space << e[1] << push << ")";
02476     break;
02477         case GRAY_SHADOW:
02478           throw SmtlibException("TheoryArithNew::print: SMTLIB: GRAY_SHADOW not supported");
02479     os << "GRAY_SHADOW(" << push << e[0] << ","  << space << e[1]
02480        << "," << space << e[2] << "," << space << e[3] << push << ")";
02481     break;
02482         default:
02483           throw SmtlibException("TheoryArithNew::print: SMTLIB: default not supported");
02484           // Print the top node in the default LISP format, continue with
02485           // pretty-printing for children.
02486           e.printAST(os);
02487 
02488           break;
02489       } 
02490       break; // end of case SMTLIB_LANG
02491     }
02492     case LISP_LANG:
02493       switch(e.getKind()) {
02494         case REAL:
02495         case INT:
02496         case RATIONAL_EXPR:
02497         case NEGINF:
02498         case POSINF:
02499           e.print(os);
02500           break;
02501         case SUBRANGE:
02502           if(e.arity() != 2) e.printAST(os);
02503           else 
02504             os << "(" << push << "SUBRANGE" << space << e[0]
02505          << space << e[1] << push << ")";
02506           break;
02507         case IS_INTEGER:
02508     if(e.arity() == 1)
02509       os << "(" << push << "IS_INTEGER" << space << e[0] << push << ")";
02510     else
02511       e.printAST(os);
02512     break;
02513         case PLUS:  {
02514           int i=0, iend=e.arity();
02515           os << "(" << push << "+";
02516           for(; i!=iend; ++i) os << space << e[i];
02517           os << push << ")";
02518           break;
02519         }
02520         case MINUS:
02521         //os << "(" << push << e[0] << space << "- " << e[1] << push << ")";
02522     os << "(" << push << "- " << e[0] << space << e[1] << push << ")";
02523           break;
02524         case UMINUS:
02525           os << "(" << push << "-" << space << e[0] << push << ")";
02526           break;
02527         case MULT:  {
02528           int i=0, iend=e.arity();
02529           os << "(" << push << "*";
02530           for(; i!=iend; ++i) os << space << e[i];
02531           os << push << ")";
02532           break;
02533         }
02534         case POW:
02535           os << "(" << push << "^ " << e[1] << space << e[0] << push << ")";
02536           break;
02537         case DIVIDE:
02538           os << "(" << push << "/ " << e[0] << space << e[1] << push << ")";
02539           break;
02540         case LT:
02541           os << "(" << push << "< " << e[0] << space << e[1] << push << ")";
02542           break;
02543         case LE:
02544           os << "(" << push << "<= " << e[0] << space << e[1] << push << ")";
02545           break;
02546         case GT:
02547           os << "(" << push << "> " << e[1]  << space << e[0] << push << ")";
02548           break;
02549         case GE:
02550           os << "(" << push << ">= " << e[0] << space << e[1] << push << ")";
02551           break;
02552         case DARK_SHADOW:
02553     os << "(" << push << "DARK_SHADOW" << space << e[0]
02554        << space << e[1] << push << ")";
02555     break;
02556         case GRAY_SHADOW:
02557     os << "(" << push << "GRAY_SHADOW" << space << e[0] << space
02558        << e[1] << space << e[2] << space << e[3] << push << ")";
02559     break;
02560         default:
02561           // Print the top node in the default LISP format, continue with
02562           // pretty-printing for children.
02563           e.printAST(os);
02564 
02565           break;
02566       } 
02567       break; // end of case LISP_LANG
02568     default:
02569      // Print the top node in the default LISP format, continue with
02570      // pretty-printing for children.
02571        e.printAST(os);
02572   }
02573   return os;
02574 }
02575 
02576 ///////////////////////////////////////////////////////////////////////////////
02577 // SIMPLEX SOLVER                                                            //
02578 ///////////////////////////////////////////////////////////////////////////////
02579 
02580 bool TheoryArithNew::isBasic(const Expr& x) const {
02581   // If it is on the right side of the tableaux the it is basic, non-basic otherwise
02582   return (tableaux.find(x) != tableaux.end());
02583 }
02584 
02585 void TheoryArithNew::pivot(const Expr& x_r, const Expr& x_s) {
02586   
02587   // Check that the variable is non-basic
02588   DebugAssert(isBasic(x_r), "TheoryArithNew::pivot, given variable should be basic" + x_r.toString());
02589   DebugAssert(!isBasic(x_s), "TheoryArithNew::pivot, given variable should be non-basic" + x_s.toString());
02590 
02591   // If trace is on for the simplex, print it out
02592   TRACE("simplex", "TheoryArithNew::pivot(", x_r.toString() + ", " + x_s.toString(), ")");
02593 
02594   // Get the iterator that points to the expression of x_r
02595   TebleauxMap::iterator it = tableaux.find(x_r); 
02596   
02597   // Get the expresiion of x_r
02598   Theorem x_r_Theorem = (*it).second;  
02599   
02600   // Erase the x_r expression from the tableaux
02601   tableaux.erase(x_r); // TODO: Add erase by iterator to ExprHashMap
02602   
02603   // Update the dependencies
02604   updateDependenciesRemove(x_r, x_r_Theorem.getExpr()[1]);
02605   
02606   // Construct the expresison (theorem) of x_s
02607   const Theorem& x_s_Theorem = pivotRule(x_r_Theorem, x_s); 
02608     
02609   // Replace all occurances of x_s with x_s_Expression
02610   substAndCanonizeTableaux(x_s_Theorem);
02611   
02612   // Update the dependencies
02613   updateDependenciesAdd(x_s, x_s_Theorem.getExpr()[1]);
02614   
02615   // Add the expression of x_s to the map
02616   tableaux[x_s] = x_s_Theorem;
02617 }
02618 
02619 void TheoryArithNew::update(const Expr& x_i, const EpsRational& v) {
02620   
02621   // Check that the variable is non-basic
02622   DebugAssert(tableaux.find(x_i) == tableaux.end(), "TheoryArithNew::update, given variable should be non-basic" + x_i.toString());
02623 
02624   // If trace is on for the simplex, print it out
02625   TRACE("simplex", "TheoryArithNew::update(", x_i.toString() + ", " + v.toString(), ")");
02626 
02627   // Remember the value of the x_i variable
02628   EpsRational old_value = getBeta(x_i);
02629 
02630   // If there are dependent variables then do the work 
02631   DependenciesMap::iterator find = dependenciesMap.find(x_i);
02632   if (find != dependenciesMap.end()) {
02633   
02634     // Go through all the variables that depend on x_i
02635     const set<Expr>& dependent = (*find).second;
02636     set<Expr>::const_iterator it     = dependent.begin();
02637     set<Expr>::const_iterator it_end = dependent.end();     
02638     // Fix the values of all the variables
02639     while (it != it_end) {
02640       
02641       // Get the current variable
02642       const Expr& x_j = *it;
02643       
02644       // Get the tableaux coefficient of the of x_i in the row of x_j (the right side ofg the tableaux expression)
02645       const Rational& a_ji = getTableauxEntry(x_j, x_i);
02646       
02647       // Update the beta valuation
02648       EpsRational b(getBeta(x_j)); // TODO: not necessary, beta's are all setup now
02649       EpsRational x_j_new = beta[x_j] = b + (v - old_value) * a_ji;
02650       
02651       // Check if the variable is sat or unsat under the new assignment 
02652       if (x_j_new < getLowerBound(x_j) || getUpperBound(x_j) < x_j_new)
02653         unsatBasicVariables.insert(x_j);
02654       else
02655         unsatBasicVariables.erase(x_j);
02656       
02657       // Go to the next one
02658       it ++;
02659     }
02660   }
02661   
02662   // Set the new value to x_i (x_i) is non_basic, no need to add to unsat set)
02663   beta[x_i] = v;
02664 }
02665       
02666 void TheoryArithNew::pivotAndUpdate(const Expr& x_i, const Expr& x_j, const EpsRational& v) {
02667   
02668   // Variable x_i should be a basic variable (left side of the tableaux) and x_j should be non_basic
02669   DebugAssert(tableaux.find(x_i) != tableaux.end(), "TheoryArithNew::pivotAndUpdate, " + x_i.toString() + " should be a basic variable");
02670   DebugAssert(tableaux.find(x_j) == tableaux.end(), "TheoryArithNew::pivotAndUpdate, " + x_j.toString() + " should be a non-basic variable");
02671 
02672   // If trace is on for the simplex, print it out
02673   TRACE("simplex", "TheoryArithNew::pivotAndUpdate(", x_i.toString() + ", " + x_j.toString() + ", " + v.toString(), ")");
02674 
02675   // The a_ij coefficient of the tableaux
02676   const Rational& a_ij = getTableauxEntry(x_i, x_j);
02677   
02678   // Let theta be the adjustment coefficient
02679   EpsRational theta((v - getBeta(x_i))/a_ij);
02680   
02681   // Set the new value to x_i (x_i becomes non-basic, hance sat)
02682   beta[x_i] = v;
02683   // x_i becomes non-basic, no need ==> it is sat
02684   unsatBasicVariables.erase(x_i);
02685   
02686   // Set the new value to x_j 
02687   EpsRational b = getBeta(x_j);
02688   EpsRational new_x_j = beta[x_j] = b + theta;
02689   
02690   // Check if the variable is sat or unsat under the new assignment 
02691   if (new_x_j < getLowerBound(x_j) || getUpperBound(x_j) < new_x_j)
02692     unsatBasicVariables.insert(x_j);
02693   else
02694     unsatBasicVariables.erase(x_j);
02695   
02696   // 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
02697   const set<Expr>& dependent = (*dependenciesMap.find(x_j)).second;
02698   set<Expr>::const_iterator it     = dependent.begin();
02699   set<Expr>::const_iterator it_end = dependent.end();     
02700   // Go throught all the basic variables
02701   while (it != it_end) {
02702     
02703     // Get the current variable
02704     const Expr& x_k = *it; 
02705     
02706     // If the basic variable is different from x_i update its value
02707     if (x_k != x_i) {
02708     
02709       // Get the a_kj coefficient from the tableaux
02710       const Rational& a_kj = getTableauxEntry(x_k, x_j);
02711       
02712       // Adjust the value (check fort sat/unsat, x_k is basic)
02713       b = getBeta(x_k);
02714       EpsRational x_k_new = beta[x_k] = b + theta * a_kj; 
02715       
02716       // Check if the variable is sat or unsat under the new assignment 
02717       if (x_k_new < getLowerBound(x_k) || getUpperBound(x_k) < x_k_new)
02718         unsatBasicVariables.insert(x_k);
02719       else
02720         unsatBasicVariables.erase(x_k);
02721     }
02722   
02723     // Go to the next one
02724     it ++;
02725   }
02726   
02727   // Last thing to do, pivot x_i and x_j
02728   pivot(x_i, x_j);
02729 }
02730       
02731 QueryResult TheoryArithNew::assertUpper(const Expr& x_i, const EpsRational& c, const Theorem& thm) {
02732   
02733   // If trace is on for the simplex, print it out
02734   TRACE("simplex", "TheoryArithNew::assertUpper(", x_i.toString() + ", " + c.toString(), ")");
02735 
02736   // Check if the given expression is actually a variable
02737   DebugAssert(isLeaf(x_i), "TheoryArithNew::assertUpper wrong kind, expected an arithmetic leaf (variable) got " + x_i.toString());
02738   
02739   // Check if the upper bound is worse then the last one
02740   if (getUpperBound(x_i) <= c) return (consistent == UNKNOWN? UNKNOWN : SATISFIABLE); 
02741   
02742   // If the new bound is lower then the lower bound */
02743   if (c < getLowerBound(x_i)) {
02744     // Create the explaining theorem
02745     explanation = d_rules->clashingBounds(getLowerBoundThm(x_i), thm);
02746     // Return unsatisfiable
02747     return UNSATISFIABLE;
02748   }
02749   
02750   // Since it is a tighter bound, propagate what can be 
02751   propagate = true;
02752 
02753   // Set the new upper bound */
02754   upperBound[x_i] = BoundInfo(c, thm);
02755 
02756   // If within the new bounds, return the previous state 
02757   if (getBeta(x_i) <= c) return (consistent == UNKNOWN? UNKNOWN : SATISFIABLE);
02758   
02759   // Otherwise, if the variable is non-basic then update it's value
02760   if (!isBasic(x_i)) update(x_i, c);
02761   // Else its basic, and non-sat, add to the unsat set
02762   else unsatBasicVariables.insert(x_i);
02763   
02764   // Everything went fine, return OK (not complete, means not UNSAT)
02765   return UNKNOWN;
02766 }
02767 
02768 QueryResult TheoryArithNew::assertLower(const Expr& x_i, const EpsRational& c, const Theorem& thm) {
02769 
02770   // Check if the given expression is actually a variable
02771   DebugAssert(isLeaf(x_i), "TheoryArithNew::assertLower wrong kind, expected an arithmetic leaf (variable) got " + x_i.toString());
02772 
02773   // If trace is on for the simplex, print it out
02774   TRACE("simplex", "TheoryArithNew::assertLower(", x_i.toString() + ", " + c.toString(), ")");
02775   
02776   // Check if the upper bound is worse then the last one
02777   if (c <= getLowerBound(x_i)) return (consistent == UNKNOWN? UNKNOWN : SATISFIABLE); 
02778   
02779   // Since it is a tighter bound, propagate what can be 
02780   propagate = true;
02781   
02782   // If the new bound is lower then the  bound */
02783   if (c > getUpperBound(x_i)) { 
02784     // Create the explaining theorem
02785     explanation = d_rules->clashingBounds(thm, getUpperBoundThm(x_i));
02786     // Return unsatisfiable
02787     return UNSATISFIABLE;
02788   }
02789   
02790   // Set the new upper bound */
02791   lowerBound[x_i] = BoundInfo(c, thm);
02792   
02793   // If within the new bounds, return the previous state 
02794   if (c <= getBeta(x_i)) return (consistent == UNKNOWN? UNKNOWN : SATISFIABLE);
02795   
02796   // Otherwise, if the variable is non-basic then update it's value
02797   if (!isBasic(x_i)) update(x_i, c);
02798   // Else its basic, and non-sat, add to the unsat set
02799   else unsatBasicVariables.insert(x_i);
02800   
02801   // Everything went fine, return OK (not complete, means not UNSAT)
02802   return UNKNOWN;
02803 }
02804       
02805 QueryResult TheoryArithNew::assertEqual(const Expr& x_i, const EpsRational& c, const Theorem& thm) {
02806   
02807   // Assert the upper bound
02808   consistent = assertUpper(x_i, c, thm); // TODO: thm: = |- <=
02809   
02810   // If the return value is UNSAT return UNSAT
02811   if (consistent == UNSATISFIABLE) return UNSATISFIABLE;
02812   
02813   // Assert the lower bound
02814   consistent = assertLower(x_i, c, thm); // TODO: thm: = |- >=
02815   
02816   // Return the consistency
02817   return consistent;
02818 }
02819 
02820 
02821 void TheoryArithNew::checkSat(bool fullEffort)
02822 { 
02823   // We should not be here if inconsistent
02824   DebugAssert(consistent != UNSATISFIABLE, "TheoryArithNew::checkSat : we are UNSAT before entering?!?!");
02825 
02826   // Trace the check sat if simplex flag is on
02827     TRACE("simplex", "TheoryArithNew::checkSat(fullEffort=",fullEffort? "true" : "false", ")");
02828   
02829     // Check if by backtracking we have more fresh variables than we expect
02830   if (assertedExprCount < assertedExpr.size()) 
02831     updateFreshVariables();
02832   
02833     // Do the simplex search if the database is not satisfiable (if inconsistent, we will not be here);
02834     if (consistent != SATISFIABLE || fullEffort)
02835       consistent = checkSatSimplex();
02836             
02837     // If the result is inconsistent set the inconsistent flag
02838     if (consistent == UNSATISFIABLE)
02839       setInconsistent(explanation);
02840     
02841     // If we are not - consistent, check the integer satisfiability
02842 //    if (consistent == SATISFIABLE) {
02843 //    // If we asserted a lemma and it hasn't been processed yet, we just don't do anything
02844 //    Theorem integer_lemma_thm = integer_lemma;
02845 //    if (!integer_lemma_thm.isNull()) {
02846 //      if (simplify(integer_lemma_thm.getExpr()).getRHS() == getEM()->trueExpr())
02847 //        consistent = checkSatInteger();
02848 //      else 
02849 //        consistent = UNKNOWN;
02850 //    } else
02851 //      // Lemma was not asserted, check integer sat
02852 //      consistent = checkSatInteger();   
02853 //    }
02854     
02855     // Trace the check sat if simplex flag is on
02856     TRACE("simplex", "TheoryArithNew::checkSat ==> ", consistent == UNSATISFIABLE? "UNSATISFIABLE" : "SATISFIABLE", "");
02857 }
02858 
02859 QueryResult TheoryArithNew::checkSatInteger() {
02860   
02861   // Trace the check sat if simplex flag is on
02862     TRACE("simplex", "TheoryArithNew::checkSatInteger()", "", "");
02863     
02864     // At this point we are REAL satisfiable, so we have to check the integers
02865   set<Expr>::iterator x_i_it     = intVariables.begin();
02866   set<Expr>::iterator x_i_it_end = intVariables.end();
02867 //  cerr << "Integer vars: ";
02868 //  while (x_i_it != x_i_it_end) {
02869 //    cerr << *x_i_it << " ";
02870 //    ++ x_i_it;
02871 //  }
02872 //  cerr << endl;
02873 //  
02874 //  x_i_it     = intVariables.begin();
02875 //  x_i_it_end = intVariables.end();
02876   while (x_i_it != x_i_it_end) {
02877     
02878     // Get the left-hand variable of the tableaux
02879     const Expr& x_i = (*x_i_it);
02880     
02881     // Only do work for unsat integer variables
02882     if (isInteger(x_i)) {
02883       
02884       // Get the current assignment of x_i
02885       const EpsRational& beta = getBeta(x_i);
02886       
02887       // Check if it is an integer
02888       if (beta.isInteger()) { ++ x_i_it; continue; }
02889       
02890       // Since the variable is not an integer, split on it being <= [beta] and >= [beta] + 1
02891       integer_lemma = d_rules->integerSplit(x_i, beta.getFloor()); 
02892       TRACE("integer", "TheoryArithNew::checkSatInteger ==> lemma : ", integer_lemma, "");
02893       enqueueFact(integer_lemma);
02894       
02895       // One split should be enough, return unknown
02896       return UNKNOWN;      
02897     }
02898     
02899     // Go to the next row
02900     ++ x_i_it;
02901   } 
02902   
02903   // We came through, huh, we are sat
02904   return SATISFIABLE; 
02905 }
02906 
02907 QueryResult TheoryArithNew::checkSatSimplex() {
02908   
02909   Expr x_i;                         // The basic variable we will use
02910   EpsRational x_i_Value;            // The current value of the variable x_i
02911   Expr x_j;                         // The non-basic variable we will use
02912   EpsRational x_j_Value;            // The current value of the variable x_j
02913   Rational a_ij;                    // The coefficient wwhen expanding x_i using x_j in the tableaux
02914   
02915   bool x_j_Found;                   // Did we find a suitable one
02916   EpsRational l_i;                  // Lower bound of x_i
02917   EpsRational u_i;                  // Upper bound of x_i
02918 
02919   // Trace the size of the tableaux and the unsat 
02920     TRACE("arith_atoms", "Tableaux size: ", tableaux.size(), "");
02921   TRACE("arith_atoms", "UNSAT vars: ", unsatBasicVariables.size(), "");
02922   
02923   // The main loop
02924   while (unsatBasicVariables.size()) {
02925    
02926     // The first unsat variable information
02927     x_i        = *unsatBasicVariables.begin();
02928     TebleauxMap::iterator it = tableaux.find(x_i); 
02929     x_i_Value  = getBeta(x_i);
02930     l_i        = getLowerBound(x_i);
02931     u_i        = getUpperBound(x_i);
02932     
02933     // If the variable doesn't obey the lower bound 
02934     if (l_i > x_i_Value) {
02935       
02936       // Did we find a suitable x_j, NOT YET
02937       x_j_Found = false; 
02938           
02939       // Find the smalles non-basic x_j that can improve x_i
02940       const Expr& x_i_RightSide = (*it).second.getExpr()[1];
02941       int non_basics_i_end     = x_i_RightSide.arity();
02942       for(int non_basics_i = 0; non_basics_i < non_basics_i_end; ++ non_basics_i) {
02943         
02944         // Get the info on the current variable
02945         x_j        = x_i_RightSide[non_basics_i][1]; 
02946         a_ij       = x_i_RightSide[non_basics_i][0].getRational(); 
02947         x_j_Value  = getBeta(x_j);           
02948         
02949         // If there is slack for improving x_i using x_j then do it               
02950         if (a_ij > 0) {
02951           if (x_j_Value < getUpperBound(x_j)) {
02952             x_j_Found = true;
02953             break;
02954           }
02955         } else {
02956           if (x_j_Value > getLowerBound(x_j)) {
02957             x_j_Found = true;
02958             break;
02959           }
02960         }     
02961       }
02962       
02963       // If none of the variables allows for slack, the tableaux is unsatisfiable
02964       if (!x_j_Found) {
02965         // Generate the explanation
02966         explanation = getLowerBoundExplanation(it);
02967         // Return unsat
02968         return UNSATISFIABLE;
02969       }
02970       
02971       // Otherwise do pivotAndUpdate and continue with the loop
02972       pivotAndUpdate(x_i, x_j, l_i);       
02973     } else
02974     // If the variable doesn't obey the upper bound 
02975     if (x_i_Value > u_i) {
02976       
02977       // Did we find a suitable x_j, NOT YET
02978       x_j_Found = false; 
02979           
02980       // Find the smalles non-basic x_j that can improve x_i
02981       const Expr& x_i_RightSide = (*it).second.getExpr()[1];
02982       int non_basics_i_end     = x_i_RightSide.arity();
02983       for(int non_basics_i = 0; non_basics_i < non_basics_i_end; ++ non_basics_i) {
02984         
02985         // Get the info on the current variable
02986         x_j        = x_i_RightSide[non_basics_i][1]; 
02987         a_ij       = x_i_RightSide[non_basics_i][0].getRational(); 
02988         x_j_Value  = getBeta(x_j);           
02989         
02990         // If there is slack for improving x_i using x_j then do it
02991         if (a_ij < 0) {
02992           if (x_j_Value < getUpperBound(x_j)) {
02993             x_j_Found = true;
02994             break;
02995           }
02996         } else 
02997           if (x_j_Value > getLowerBound(x_j)) {
02998             x_j_Found = true;
02999             break;
03000           }     
03001       }
03002       
03003       // If none of the variables allows for slack, the tableaux is unsatisfiable
03004       if (!x_j_Found) {
03005         // Generate the explanation
03006         explanation = getUpperBoundExplanation(it);
03007         // Return unsat
03008         return UNSATISFIABLE; 
03009       }
03010       
03011       // Otherwise do pivotAndUpdate and continue with the loop
03012       pivotAndUpdate(x_i, x_j, u_i);       
03013     } else
03014       // Due to backtracking a unsat might become sat, just erase it
03015       unsatBasicVariables.erase(x_i);
03016       
03017     
03018     // If trace is on, printout the current valuation and the tableaux
03019     TRACE("simplex", "TheoryArithNew::checkSatSimplex ==> new tableaux : \n", tableauxAsString(), "");
03020     TRACE("simplex", "TheoryArithNew::checkSatSimplex ==> new bounds   : \n", boundsAsString(), "");
03021     TRACE("simplex", "TheoryArithNew::checkSatSimplex ==> unsat   : \n", unsatAsString(), "");
03022     
03023   };
03024 
03025   // Since there is no more unsat constraints we are satisfiable
03026   return SATISFIABLE;
03027 }     
03028 
03029 Rational TheoryArithNew::getTableauxEntry(const Expr& x_i, const Expr& x_j) {
03030   return findCoefficient(x_j, tableaux[x_i].getExpr()[1]);
03031 }
03032 
03033 
03034 const Rational& TheoryArithNew::findCoefficient(const Expr& var, const Expr& expr) {
03035 
03036   // The zero coefficient 
03037   static Rational zeroCoefficient(0);
03038 
03039     // The given expression must be a sum
03040     DebugAssert(isPlus(expr), "TheoryArithNew::findCoefficient : expression must be a sum : " + expr.toString());
03041   
03042   // Go through the sum and find the coefficient
03043   int left = 0;
03044   int right = expr.arity() - 1;
03045   int i;
03046   while (left <= right) {
03047     
03048     // Take the middle one
03049     i = (left + right ) / 2;
03050     
03051     // Current expression
03052     const Expr& mult = expr[i];
03053     
03054     // Every summand must be a multiplication with a rational
03055     DebugAssert(isMult(mult) && isRational(mult[0]), "TheoryArithNew::findCoefficient : expression must be a sum of multiplications: " + expr.toString()); 
03056     
03057     // If the variable is the same return the coefficient
03058     int cmp = compare(mult[1], var);
03059     if (cmp == 0) 
03060       return mult[0].getRational();
03061     else 
03062       if (cmp > 0) 
03063         left = i + 1;
03064       else 
03065         right = i - 1;    
03066   }
03067     
03068   // Not found, return 0
03069   return zeroCoefficient; 
03070 }
03071 
03072 
03073 TheoryArithNew::EpsRational TheoryArithNew::getLowerBound(const Expr& x) const {
03074   // Try and find the lower bound in the map
03075   CDMap<Expr, BoundInfo>::iterator find = lowerBound.find(x);
03076   // If not found return +infinity as the default value, othervise return the value
03077   if (find == lowerBound.end()) return EpsRational::MinusInfinity;
03078   else return (*find).second.bound;
03079 }
03080 
03081 TheoryArithNew::EpsRational TheoryArithNew::getUpperBound(const Expr& x) const {
03082   // Try and find the upper bound in the map
03083   CDMap<Expr, BoundInfo>::iterator find = upperBound.find(x);
03084   // If not found return -infinity as the default value, othervise return the value
03085   if (find == upperBound.end()) return EpsRational::PlusInfinity;
03086   else return (*find).second.bound;
03087 }
03088 
03089 Theorem TheoryArithNew::getLowerBoundThm(const Expr& x) const {
03090   // Try and find the upper bound in the map
03091   CDMap<Expr, BoundInfo>::iterator find = lowerBound.find(x);
03092   // It has to be found
03093   DebugAssert(find != lowerBound.end(), "TheoryArithNew::getLowerBoundThm, theorem not found for " + x.toString()); 
03094   // Return the bound theorem 
03095   return (*find).second.theorem;
03096 }
03097 
03098 Theorem TheoryArithNew::getUpperBoundThm(const Expr& x) const {
03099   // Try and find the upper bound in the map
03100   CDMap<Expr, BoundInfo>::iterator find = upperBound.find(x);
03101   // It has to be found
03102   DebugAssert(find != upperBound.end(), "TheoryArithNew::getUpperBoundThm, theorem not found for " + x.toString()); 
03103   // Return the bound theorem 
03104   return (*find).second.theorem;
03105 }
03106 
03107       
03108 TheoryArithNew::EpsRational TheoryArithNew::getBeta(const Expr& x) {
03109   
03110   // Try to find the beta value in the map
03111   CDMap<Expr, EpsRational>::iterator find = beta.find(x);
03112   
03113   if (find == beta.end()) {
03114     // If not found return 0 (no need for sat/unsat, it's allways sat) 
03115     return beta[x] = EpsRational::Zero;
03116   
03117     // Check if the variable is sat or unsat under the new assignment 
03118     if (EpsRational::Zero < getLowerBound(x) || getUpperBound(x) < EpsRational::Zero)
03119       unsatBasicVariables.insert(x);
03120     else
03121       unsatBasicVariables.erase(x);
03122   }
03123   else 
03124     // If found, just return it
03125     return (*find).second;
03126 }
03127 
03128 
03129 void TheoryArithNew::assertFact(const Theorem& assertThm)
03130 {
03131   // Get the expression to be asserted
03132   const Expr& expr = assertThm.getExpr();
03133 
03134   // If tracing arithmetic, print out the expression to be asserted
03135   TRACE("simplex", "TheoryArithNew::assertFact(", expr, ")");
03136   TRACE("simplex", "asserted: ", assertedExpr.size(), "");
03137   TRACE("simplex", "counted: ", assertedExprCount, "");
03138   TRACE("arith_atoms", "Assert: ", expr.toString(), "");
03139             
03140   // Check if by backtracking we have more fresh variables than we expect
03141   if (assertedExprCount < assertedExpr.size()) 
03142     updateFreshVariables();
03143   
03144   // Get the constraint partsreturn 
03145   const Expr& leftSide   = expr[0];          // The left side of the constraint  
03146   const Expr& rightSide  = expr[1];          // The right side of the constraint
03147   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
03148   
03149   // The expression must be an inequality (sum a_1*x_1 .. a_n*x_n) @ b
03150   DebugAssert(isIneq(expr)         , "TheoryArithNew::assertFact wrong kind, expected inequality"                 + expr.toString());
03151   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());
03152   DebugAssert(isRational(leftSide), "TheoryArithNew::assertFact wrong kind, expected rational on the right side" + expr.toString());
03153 
03154   // Get the rational value on the right side 
03155   Rational leftSideValue = leftSide.getRational(); 
03156   
03157   // The rational bound on the constraint
03158   Rational c = leftSideValue;
03159   
03160   // The variable to be constrained
03161   Expr var;       
03162   
03163   // Theorem of the assertion
03164   Theorem assert = assertThm;                                 
03165   
03166   // For now we have that leftSide @ (c1x1 + c2x2 + ... cnxn) = rightSide
03167   // If rightSide is not a sum constraint is atomic (leftSide @ a*x)
03168   if (!isPlus(rightSide)) {
03169     
03170     // Tee left side in this case should be 1*x
03171     DebugAssert(rightSide[0].isRational() && rightSide[0].getRational() == 1, "TheoryArithNew::assertFact, left side should be multiplication by one");
03172     
03173     // Change the assert theorem to remove the 1*x to x
03174     assert = iffMP(assert, substitutivityRule(expr, reflexivityRule(leftSide), d_rules->oneElimination(rightSide)));
03175     
03176     // The variable will just be x1 (if var is not already present in the tableaux, it will be non-basic)
03177     var = rightSide[1]; // IMPORTANT!!!, when giving explanations, it should be of the same form
03178     
03179     // If an integer, add it to the integer set
03180     if (isInteger(var)) intVariables.insert(var);
03181           
03182   } else {
03183     // Get the theorem that corresponds to the introduction of the new variable var = leftSide 
03184     const Theorem& introductionThm = getVariableIntroThm(rightSide);
03185     
03186     // Take the new variable out
03187     var = introductionThm.getExpr()[0];
03188 
03189     // Change the theorem for the assertion so that it involves the new variable, i.e.  c < rightSide, var = rightSide |- c < var
03190     assert = iffMP(assertThm, substitutivityRule(expr, 1, symmetryRule(introductionThm)));
03191     
03192     // Insert all the integer variables into the integer set
03193     if (isInteger(var)) {
03194       intVariables.insert(var);
03195       int i_end = rightSide.arity();
03196       for(int i = 0; i < i_end; ++ i)
03197         intVariables.insert(rightSide[i][1]);
03198     } else {
03199       int i_end = rightSide.arity();
03200       for(int i = 0; i < i_end; ++ i)
03201         if (isInteger(rightSide[i][1])) intVariables.insert(rightSide[i][1]);
03202     }
03203   }
03204   
03205   // Make the BoundInfo object for theory propagation
03206   EpsRational bound;
03207   
03208   // By default we don't propagate
03209   propagate = false;
03210   
03211   // Remember the old bound
03212   EpsRational oldBound;
03213   
03214   // Finnaly assert the right constraint
03215   switch (kind) {
03216     case LT: 
03217       oldBound    = getLowerBound(var);
03218       // c < var, convert to c + epsilon <= var and assert it
03219       consistent = assertLower(var, bound = EpsRational(c, +1), assert);
03220       break;          
03221     case LE:
03222       oldBound    = getLowerBound(var);
03223       // c <= var, assert the lower bound
03224       consistent = assertLower(var, bound = c, assert);
03225       break;
03226     case GT: 
03227       oldBound    = getUpperBound(var);
03228       // c > var, convert to c - epsilon >= var and assert it
03229       consistent = assertUpper(var, bound = EpsRational(c, -1), assert);
03230       break;
03231     case GE:
03232       oldBound    = getUpperBound(var);
03233       // c >= var, assert the upper bound
03234       consistent = assertUpper(var, bound = c, assert);
03235       break;
03236     case EQ:
03237       // c == var, assert the equality
03238       consistent = assertEqual(var, bound = c, assert);
03239       // For now, don't propagate anything
03240       propagate = false; // TODO: some propagation is in place here (negations)     
03241       break;
03242     default:
03243       //How did we get here
03244           FatalAssert(false, "Theory_Arith::assertFact, control should not reach here");
03245           break;
03246   } 
03247   
03248   // If tracing arithmetic, print out the new tableaux and the current bounds
03249   TRACE("simplex", "TheoryArithNew::assertFact ==> ", consistent == UNSATISFIABLE? "UNSATISFIABLE" : consistent == UNKNOWN? "UNKNOWN" : "SATISFIABLE", "");
03250   TRACE("simplex", "TheoryArithNew::assertFact ==> new tableaux : \n", tableauxAsString(), "");
03251   TRACE("simplex", "TheoryArithNew::assertFact ==> new bounds   : \n", boundsAsString(), "");
03252   TRACE("simplex", "TheoryArithNew::assertFact ==> unsat   : \n", unsatAsString(), "");
03253   
03254   // If the result is inconsistent set the inconsistent flag
03255     if (consistent == UNSATISFIABLE)
03256       setInconsistent(explanation);
03257       
03258     // Not inconsistent, propagate all from this assertion
03259     if (propagate) 
03260       propagateTheory(assertThm.getExpr(), bound, oldBound);    
03261 }
03262 
03263 
03264 Theorem TheoryArithNew::getVariableIntroThm(const Expr& rightSide) {
03265   
03266   // Try to find the expression in the map
03267   TebleauxMap::iterator find = freshVariables.find(rightSide);
03268   
03269   // If not in tableaux, add it and assign it a new variable
03270   if (find == freshVariables.end()) {
03271   
03272     // Get the common rules
03273     CommonProofRules* c_rules = getCommonRules();
03274   
03275     // Create a new variable (\exists x . rightSide = x)
03276     Theorem thm = c_rules->varIntroRule(rightSide);
03277       
03278       // Skolemise it, to get an equality (\exists x . rightSide = x) <==> rightSide = c, then infer |- rightSide = c
03279       thm = c_rules->iffMP(thm, c_rules->skolemizeRewrite(thm.getExpr()));    
03280       
03281       // Reverse the equality into standard form
03282       thm = symmetryRule(thm);
03283       
03284       // Add the theorem to the variable introduction map (this is the theorem we return)
03285       Theorem returnThm = freshVariables[rightSide] = thm;
03286       
03287       // Now, flatten the equality modulo tableaux
03288       thm = substAndCanonizeModTableaux(thm);
03289       
03290       // Get the skolem constant that was introduced (|- c = leftSide)
03291       const Expr& var = thm.getExpr()[0];
03292             
03293       // Also add it to the tableaux
03294       tableaux[var] = thm;
03295 
03296     // Update the dependencies
03297     updateDependenciesAdd(var, thm.getExpr()[1]);
03298 
03299     // Add it to the expressions map
03300     assertedExpr.push_back(Expr(EQ, var, rightSide));
03301     assertedExprCount = assertedExprCount + 1;
03302       
03303       // Compute the value of the new variable using the tableaux
03304     updateValue(var, rightSide);
03305             
03306       // Return the variable
03307       return returnThm;
03308   }
03309   
03310   // Otherwise we have it, so return it
03311   return (*find).second;
03312 }
03313 
03314 void TheoryArithNew::updateValue(const Expr& var, const Expr& e) {
03315   
03316     // The initial value
03317     EpsRational varValue(0);
03318     
03319     // Go through the sum and compute the value
03320     int i_end = e.arity();
03321     for (int i = 0; i < i_end; ++ i)
03322       varValue += getBeta(e[i][1]) * e[i][0].getRational();
03323     
03324     // Update the beta  
03325     beta[var] = varValue;
03326     
03327     // Check if the variable is sat or unsat under the new assignment 
03328   if (varValue < getLowerBound(var) || getUpperBound(var) < varValue)
03329     unsatBasicVariables.insert(var);
03330   else
03331     unsatBasicVariables.erase(var);
03332 }
03333 
03334 string TheoryArithNew::tableauxAsString() const {
03335 
03336   // The string we are building 
03337   string str; 
03338 
03339   // Start from the begining
03340   TebleauxMap::const_iterator row     = tableaux.begin();
03341   TebleauxMap::const_iterator row_end = tableaux.end(); 
03342   
03343   // Print all the rows
03344   while (row != tableaux.end()) {
03345     // Print the equality
03346     str = str + ((*row).second).getExpr().toString() + "\n";
03347     
03348     // Continue to the next row
03349     row ++;
03350   }
03351   
03352   // Return the string representation 
03353   return str;
03354 }
03355 
03356 string TheoryArithNew::unsatAsString() const {
03357 
03358   // The string we are building 
03359   string str; 
03360 
03361   // Start from the begining
03362   set<Expr>::const_iterator it     = unsatBasicVariables.begin();
03363   set<Expr>::const_iterator it_end = unsatBasicVariables.end(); 
03364   
03365   // Print all the rows
03366   while (it != it_end) {
03367     // Print the equality
03368     str = str + (*it).toString() + " ";
03369     
03370     // Continue to the next row
03371     it ++;
03372   }
03373   
03374   // Return the string representation 
03375   return str;
03376 }
03377 
03378 
03379 string TheoryArithNew::boundsAsString() {
03380 
03381   // The string we are building 
03382   string str; 
03383 
03384   // Set containing all the variables
03385   set<Expr> all_variables;
03386   
03387   // Go throught the tableaux and pick up all the variables
03388   TebleauxMap::const_iterator it     = tableaux.begin();
03389   TebleauxMap::const_iterator it_end = tableaux.end();
03390   for(; it != it_end; it ++) {
03391   
03392     // Add the basic variable to the set
03393     all_variables.insert((*it).first);
03394     
03395     // Go through all the expression variables and add them to the set
03396     const Expr& rightSide = (*it).second.getExpr()[1];
03397     int term_i_end = rightSide.arity();
03398     for(int term_i = 0; term_i < term_i_end; ++ term_i)
03399       all_variables.insert(rightSide[term_i][1]); 
03400   } 
03401   
03402   // Go throught the bounds map and pickup all the variables
03403   CDMap<Expr, BoundInfo>::iterator bounds_it;
03404   for (bounds_it = lowerBound.begin(); bounds_it != lowerBound.end(); bounds_it ++)
03405     all_variables.insert((*bounds_it).first);
03406   for (bounds_it = upperBound.begin(); bounds_it != upperBound.end(); bounds_it ++)
03407     all_variables.insert((*bounds_it).first);
03408     
03409   // Start from the begining
03410   set<Expr>::iterator var_it     = all_variables.begin();
03411   set<Expr>::iterator var_it_end = all_variables.end(); 
03412   
03413   // Print all the rows
03414   while (var_it != var_it_end) {
03415     
03416     // The current variable
03417     const Expr& var = *var_it;
03418     
03419     // Print the equality
03420     str += getLowerBound(var).toString() + " <= " + var.toString() + "(" + getBeta(var).toString() + ") <= " + getUpperBound(var).toString() + "\n";
03421       
03422     // Continue to the next variable
03423     var_it ++;
03424   }
03425   
03426   // Return the string representation 
03427   return str;
03428 }
03429 
03430 // The infinity constant 
03431 const TheoryArithNew::EpsRational TheoryArithNew::EpsRational::PlusInfinity(PLUS_INFINITY);
03432 // The negative infinity constant
03433 const TheoryArithNew::EpsRational TheoryArithNew::EpsRational::MinusInfinity(MINUS_INFINITY);
03434 // The negative infinity constant
03435 const TheoryArithNew::EpsRational TheoryArithNew::EpsRational::Zero;
03436 
03437 
03438 Theorem TheoryArithNew::substAndCanonizeModTableaux(const Theorem& eq) {
03439 
03440   // If subst is empty, just return
03441     if(tableaux.empty()) return eq;
03442 
03443   // Get the expression of the equality
03444   const Expr& eqExpr = eq.getExpr();
03445 
03446   // Check if the equality if in the canonic form
03447   DebugAssert(eqExpr.getKind() == EQ, "TheoryArithNew::substAndCanonize, expected equality " + eqExpr.toString());
03448   
03449   // Get the left side of the equality
03450   const Expr& rightSide = eqExpr[1];
03451 
03452     // Do the actual substitution in the eqExpr
03453     Theorem thm = substAndCanonizeModTableaux(rightSide);
03454   
03455     // If the substitution had no result just return the original equation
03456     if(thm.getRHS() == rightSide) return eq;
03457     
03458     // Return the theorem 
03459     return iffMP(eq, substitutivityRule(eq.getExpr(), 1, thm));
03460 }
03461 
03462 Theorem TheoryArithNew::substAndCanonizeModTableaux(const Expr& sum) {
03463     
03464     Theorem res;                      // The resulting theorem    
03465     vector<Theorem> thms;             // The theorems of the changed terms for the substitution
03466     vector<unsigned> changed;         // The indices of the changed terms for the substitution
03467   
03468   // Trace the canonisation
03469   TRACE("simplex", "TheoryArithNew::substAndCanonizeModTableaux(", sum, ")");
03470   
03471   // Check if the equality if in the canonic form
03472   DebugAssert(sum.getKind() == PLUS, "TheoryArithNew::substAndCanonize, expected sum " + sum.toString());
03473    
03474     // Go throught the sum and try to substitute the variables
03475     int term_index_end = sum.arity();
03476     for(int term_index = 0; term_index < term_index_end; ++ term_index) {
03477 
03478     const Expr& term = sum[term_index]; // The current term expression (a*x)
03479     const Expr& var  = term[1];         // The variable of the current term
03480   
03481       // Find the variable in the map
03482       TebleauxMap::iterator find = tableaux.find(var);
03483       
03484       // If found, substitute it
03485       if (find != tableaux.end()) {
03486         
03487         // Substitute the variable
03488         Theorem termTheorem = canonThm(substitutivityRule(term, 1, (*find).second));
03489         
03490         // Check that the result is not trivial 
03491         DebugAssert(termTheorem.getExpr() != term, "substAndCanonizeModTableaux: got the same term in substitution");
03492           
03493       // Push it to the theorems vector
03494           thms.push_back(termTheorem);
03495           
03496           // Add the index to the changed vector
03497           changed.push_back(term_index);      
03498       }     
03499     }
03500   
03501     // Do the actual substitution and canonize the result
03502     if(thms.size() > 0) {
03503       // Substitute the changed subterms into the term
03504       res = substitutivityRule(sum, changed, thms);
03505       // Canonise the result
03506       res = canonThm(res);
03507     } else
03508       // Nothing happened, just return the reflexivity
03509       res = reflexivityRule(sum);     
03510   
03511     // Return the result
03512     return res;
03513 }
03514 
03515 void TheoryArithNew::substAndCanonizeTableaux(const Theorem& eq) {
03516 
03517   Theorem result; // The explaining theorem
03518     
03519   // Trace 
03520   TRACE("simplex", "TheoryArithNew::substAndCanonizeTableaux(", eq.getExpr(), ")");
03521     
03522   // Get the expression of the equality
03523   const Expr& eqExpr = eq.getExpr();
03524 
03525   // Check if the equality if in the canonic form
03526   DebugAssert(eqExpr.getKind() == EQ, "TheoryArithNew::substAndCanonize, expected equality " + eqExpr.toString());
03527   
03528   // Get the variable of the substitution
03529   const Expr& var = eqExpr[0];
03530 
03531   // Check if there are variables that depend on x_j
03532   DependenciesMap::iterator find = dependenciesMap.find(var);
03533   if (find != dependenciesMap.end()) {
03534       
03535     // Go through all the variables that depend on x_j, and update their value
03536     set<Expr>& dependent = (*find).second;
03537     set<Expr>::iterator it     = dependent.begin();
03538     set<Expr>::iterator it_end = dependent.end();     
03539     for(; it != it_end; ++ it) {
03540       
03541       // Get the expression and the right side of the row from the tableaux
03542       const Expr& leftSide      = *it;
03543       TebleauxMap::iterator row = tableaux.find(leftSide);
03544       const Expr& rowExpr       = (*row).second.getExpr();
03545       const Expr& rowRightSide  = rowExpr[1];
03546       
03547       // Go through the sum and try to substitute
03548       int right = rowRightSide.arity() - 1;
03549       int left  = 0;
03550       int term_i;
03551       while (left <= right) { 
03552         
03553         // Get the middle one
03554         term_i = (left + right) / 2;
03555         
03556         // Get the comparison of the variables
03557         int cmp = compare(rowRightSide[term_i][1], var);
03558               
03559         // If the variable is found
03560         if (cmp == 0) {
03561           
03562           // Do the substitution and canonise
03563           result = canonThm(substitutivityRule(rowRightSide[term_i], 1, eq));
03564           // Do the substitution and canonise in the sum
03565           result = canonThm(substitutivityRule(rowRightSide, term_i, result));
03566           // Do the substitution
03567           result = substitutivityRule(rowExpr, 1, result);
03568           
03569           // Get the new expression
03570           const Expr& newRowRightSide = result.getRHS()[1];       
03571           // Update the dependencies of the varriables in the expression
03572           updateDependencies(rowRightSide, newRowRightSide, leftSide, var); 
03573           
03574           // That's it, remember the new row
03575           (*row).second = iffMP((*row).second, result);       
03576           
03577           // Variables don't repeat, we can just break out        
03578           break;
03579         } else if (cmp > 0) 
03580           left = term_i + 1;
03581         else 
03582           right = term_i - 1;
03583       }
03584     }
03585     
03586     // Now nobody depends on var anymore, just erase it
03587       dependent.clear();
03588   } 
03589 }
03590 
03591 Theorem TheoryArithNew::pivotRule(const Theorem& eq, const Expr& var) {
03592 
03593   Theorem result;  // The theorem explaining the result
03594 
03595   // Get the expression
03596   const Expr& eqExpr = eq.getExpr();
03597   const Expr& right_side = eqExpr[1];
03598   const Expr& left_side = eqExpr[0];
03599 
03600   // Trace if askedTheorem canonLeft  = d_rules->canonMult(thm.getExpr()[0]);
03601       
03602   TRACE("simplex", "TheoryArithNew::pivotRule(", eqExpr.toString() + ", ", var.toString() + ")"); 
03603 
03604   // Eq must be an equation with the sum on the left side and a leaf on the right side (variable)
03605   DebugAssert(eqExpr.getKind() == EQ, "TheoryArithNew::pivotRule, expected an equality : " + eqExpr.toString());
03606   DebugAssert(right_side.getKind() == PLUS, "TheoryArithNew::pivotRule, expected a sum on the left-hand side : " + eqExpr.toString());
03607   DebugAssert(isLeaf(left_side), "TheoryArithNew::pivotRule, expected a leaf (variable) on the right-hand side : " + eqExpr.toString());
03608 
03609   // Find the term of var in the left-hand side of eq
03610   int term_i_end = right_side.arity();
03611   for(int term_i = 0; term_i < term_i_end; ++ term_i)
03612     // If found do the stuff
03613     if (right_side[term_i][1] == var) {
03614   
03615       // This is the term we need and the rational we need
03616       const Expr& termExpr = right_side[term_i];
03617       const Expr& termVar = termExpr[1]; 
03618       const Rational& termRat = termExpr[0].getRational();
03619       
03620       // Construct the expression we will add to the equality
03621       const Expr& minusTermExpr = multExpr(rat(-termRat), termVar);
03622       const Expr& minusVarExpr  = multExpr(rat(-1), left_side); 
03623     
03624       // Add the above expressions to the to the equality
03625       result = iffMP(eq, d_rules->plusPredicate(left_side, right_side, plusExpr(minusTermExpr, minusVarExpr), EQ));
03626       // Canonise the right-hand side
03627       result = transitivityRule(result, canon(result.getExpr()[1]));
03628       // Canonise the left-hand side 
03629       result = transitivityRule(symmetryRule(canon(result.getExpr()[0])), result);
03630       // Multiply by the inverse of the rational constant (negated and ^-1)
03631       result = iffMP(result, d_rules->multEqn(result.getExpr()[0], result.getExpr()[1], rat(-1/termRat)));
03632       // Canonise the left-hand side
03633       result = transitivityRule(result, canon(result.getExpr()[1]));
03634       // Canonise the right=hand side 
03635       result = transitivityRule(symmetryRule(canon(result.getExpr()[0])), result);
03636       // Rewrite 1*x => x in the left-hand side
03637       result = transitivityRule(symmetryRule(d_rules->oneElimination(result.getExpr()[0])), result);
03638       
03639       // Trace the result
03640       TRACE("simplex", "TheoryArithNew::pivotRule ==> ", result.getExpr().toString(), "");
03641       
03642       // We are done, there is just one variable there
03643       return result;
03644     }
03645   
03646   // If not found, there is something wrong
03647   DebugAssert(false, "TheoryArithNew::pivotRule, " + var.toString() + " does not occur in " + eqExpr.toString());
03648 
03649   // Dummy return 
03650   return result;
03651 }
03652 
03653 Theorem TheoryArithNew::getLowerBoundExplanation(const TebleauxMap::iterator& var_it) {
03654 
03655   vector<Theorem> upperBounds; // Vector of the upper-bound theorems 
03656   
03657   // Get the tableaux theorem explaining the leftside = var
03658   Theorem tableauxTheorem = (*var_it).second;
03659   
03660   // Get the variable on the right side
03661   const Expr& var = (*var_it).first;
03662 
03663   // Get the expression involved (leftSide = var)
03664   const Expr& rightSide = tableauxTheorem.getExpr()[1];
03665   
03666   // Go through the left side and pick up the apropriate lower and upper bounds
03667   int leftSide_i_end = rightSide.arity();
03668   for(int leftSide_i = 0; leftSide_i < leftSide_i_end; ++ leftSide_i) {
03669 
03670     // Get the rational
03671     const Expr& a = rightSide[leftSide_i][0];
03672     
03673     // Get the variable
03674     const Expr& x = rightSide[leftSide_i][1];
03675     
03676     // The positive ones make up the upper bounds (x < u => a * x < a * u)
03677     if (a.getRational() > 0) {
03678       // Get the upper bound x < u
03679       Theorem thm = getUpperBoundThm(x);
03680       
03681       // Multiply if by a ==> u_i * a > x * a
03682       thm = iffMP(thm, d_rules->multIneqn(thm.getExpr(), a));
03683     
03684       // Canonise the left and the right side
03685       Theorem canonRight  = d_rules->canonMultTermConst(thm.getExpr()[1][1], thm.getExpr()[1][0]);
03686       Theorem canonLeft = d_rules->canonMultConstConst(thm.getExpr()[0][0], thm.getExpr()[0][1]); 
03687       
03688       // Substitute the canonised to the inequality
03689       thm = iffMP(thm, substitutivityRule(thm.getExpr(), canonLeft, canonRight));
03690       
03691       // Add the bound to the vector of upper bounds (|- c_x > a * x) 
03692       upperBounds.push_back(thm);
03693     } 
03694     // The negative ones make up the lower bounds (x > l => a * x < a * l)
03695     else {
03696       // Get the lower bound l < x
03697       Theorem thm = getLowerBoundThm(x);
03698       
03699       // Multiply if by a |- l * a < x * a  
03700       thm = iffMP(thm, d_rules->multIneqn(thm.getExpr(), a));
03701     
03702       // Canonise the left and the right side
03703       Theorem canonRight  = d_rules->canonMultTermConst(thm.getExpr()[1][1], thm.getExpr()[1][0]);
03704       Theorem canonLeft = d_rules->canonMultConstConst(thm.getExpr()[0][0], thm.getExpr()[0][1]); 
03705       
03706       // Substitute the canonised to the inequality
03707       thm = iffMP(thm, substitutivityRule(thm.getExpr(), canonLeft, canonRight));
03708       
03709       // Add the bound to the vector of upper bounds (|- c_x > a * x)
03710       upperBounds.push_back(thm);
03711     }
03712   } 
03713   
03714   // Add up all the inequalities to get a C = \sum c_i > rightSide 
03715   Theorem sumInequalities = upperBounds[0];
03716   for(unsigned int i = 1; i < upperBounds.size(); i ++) { 
03717     // Add the inequalities
03718     sumInequalities = d_rules->addInequalities(sumInequalities, upperBounds[i]);
03719     
03720     // Canonise the left and the right side
03721     Theorem canonLeft  = d_rules->canonPlus(sumInequalities.getExpr()[0]);
03722     Theorem canonRight = d_rules->canonPlus(sumInequalities.getExpr()[1]);
03723     
03724     // Substitute the canonised to the inequality
03725     sumInequalities = iffMP(sumInequalities, substitutivityRule(sumInequalities.getExpr(), canonLeft, canonRight));   
03726   }
03727   
03728   // Substitute to get C > rightSide ==> C > var
03729   Theorem varUpperBound = substitutivityRule(sumInequalities.getExpr(), 1, symmetryRule(tableauxTheorem));  
03730   // MP to get C > var
03731   varUpperBound = iffMP(sumInequalities, varUpperBound);
03732   
03733   // Get the lower bound on the rigth side variable (l_var < var)
03734   Theorem varLowerBound = getLowerBoundThm(var);
03735 
03736   // Return the clashing bound theorem 
03737   return d_rules->clashingBounds(varLowerBound, varUpperBound);
03738 }
03739 
03740 Theorem TheoryArithNew::getUpperBoundExplanation(const TebleauxMap::iterator& var_it) {
03741 
03742   vector<Theorem> lowerBounds; // Vector of the upper-bound theorems 
03743   
03744   // Get the tableaux theorem explaining the leftside = var
03745   Theorem tableauxTheorem = (*var_it).second;
03746   
03747   // Get the variable on the right side
03748   const Expr& var = (*var_it).first;
03749 
03750   // Get the expression involved (var = rightSide)
03751   const Expr& rightSide = tableauxTheorem.getExpr()[1];
03752   
03753   // Trace if requested
03754   TRACE("explanations", "Generating explanation for the tableaux row ", tableauxTheorem.getExpr(), "");
03755   
03756   // Go through the right side and pick up the apropriate lower and upper bounds
03757   int rightSide_i_end = rightSide.arity();
03758   for(int rightSide_i = 0; rightSide_i < rightSide_i_end; ++ rightSide_i) {
03759 
03760     // Get the rational
03761     const Expr& a = rightSide[rightSide_i][0];
03762     
03763     // Get the variable
03764     const Expr& x = rightSide[rightSide_i][1];
03765     
03766     // The positive ones make up the lower bounds (x > l => a * x > a * l)
03767     if (a.getRational() > 0) {
03768       // Get the lower bound l < x
03769       Theorem thm = getLowerBoundThm(x);
03770       TRACE("explanations", "Got ", thm.getExpr(), "");
03771       
03772       // Multiply if by a ==> l * a < x * a
03773       thm = iffMP(thm, d_rules->multIneqn(thm.getExpr(), a));
03774       TRACE("explanations", "Got ", thm.getExpr(), "");
03775     
03776       // Canonise the left and the right side
03777       Theorem canonRight  = d_rules->canonMultTermConst(thm.getExpr()[1][1], thm.getExpr()[1][0]);
03778       Theorem canonLeft = d_rules->canonMultConstConst(thm.getExpr()[0][0], thm.getExpr()[0][1]); 
03779       
03780       // Substitute the canonised to the inequality
03781       thm = iffMP(thm, substitutivityRule(thm.getExpr(), canonLeft, canonRight));
03782       TRACE("explanations", "Got ", thm.getExpr(), "");
03783       
03784       // Add the bound to the vector of upper bounds (|- c_x < a * x) 
03785       lowerBounds.push_back(thm);
03786     } 
03787     // The negative ones make up the upper bounds (x < u => a * x > a * u)
03788     else {
03789       // Get the upper bound u > x
03790       Theorem thm = getUpperBoundThm(x);
03791       TRACE("explanations", "Got ", thm.getExpr(), "");
03792     
03793       // Multiply it by a |- u * a > x * a 
03794       thm = iffMP(thm, d_rules->multIneqn(thm.getExpr(), a));
03795       TRACE("explanations", "Got ", thm.getExpr(), "");
03796     
03797       // Canonise the left and the right side
03798       Theorem canonRight = d_rules->canonMultTermConst(thm.getExpr()[1][1], thm.getExpr()[1][0]);
03799       Theorem canonLeft  = d_rules->canonMultConstConst(thm.getExpr()[0][0], thm.getExpr()[0][1]); 
03800       
03801       // Substitute the canonised to the inequality
03802       thm = iffMP(thm, substitutivityRule(thm.getExpr(), canonLeft, canonRight));
03803       TRACE("explanations", "Got ", thm.getExpr(), "");
03804       
03805       // Add the bound to the vector of upper bounds (|- c_x < a * x)
03806       lowerBounds.push_back(thm);
03807     }
03808   } 
03809   
03810   // Add up all the inequalities to get a \sum c_i = C > rightSide
03811   Theorem sumInequalities = lowerBounds[0];
03812   for(unsigned int i = 1; i < lowerBounds.size(); i ++) { 
03813     // Add the inequalities
03814     sumInequalities = d_rules->addInequalities(sumInequalities, lowerBounds[i]);
03815     
03816     TRACE("explanations", "Got sum ", sumInequalities.getExpr(), "");
03817     
03818     // Canonise the left and the right side
03819     Theorem canonLeft  = d_rules->canonPlus(sumInequalities.getExpr()[0]);
03820     Theorem canonRight = d_rules->canonPlus(sumInequalities.getExpr()[1]);
03821     
03822     // Substitute the canonised to the inequality
03823     sumInequalities = iffMP(sumInequalities, substitutivityRule(sumInequalities.getExpr(), canonLeft, canonRight));   
03824   }
03825   
03826   // Trace if requested
03827   TRACE("explanations", "Got sum ", sumInequalities.getExpr(), "");
03828 
03829   // Substitute to get C < leftSide ==> C < var
03830   Theorem varLowerBound = substitutivityRule(sumInequalities.getExpr(), 1, symmetryRule(tableauxTheorem));  
03831   
03832   // MP to get C < var
03833   varLowerBound = iffMP(sumInequalities, varLowerBound);
03834 
03835   // Trace if requested
03836   TRACE("explanations", "Got lower bound ", varLowerBound.getExpr(), "");
03837   
03838   // Get the lower bound on the rigth side variable (var > l_var)
03839   Theorem varUpperBound = getUpperBoundThm(var);
03840 
03841   // Trace if requested
03842   TRACE("explanations", "Got upper bound ", varUpperBound.getExpr(), "");
03843 
03844   TRACE("explanations", "The var value (", var, ")" + getBeta(var).toString());
03845 
03846   // Return the clashing bound theorem 
03847   return d_rules->clashingBounds(varLowerBound, varUpperBound);
03848 }
03849 
03850 void TheoryArithNew::updateFreshVariables() {
03851 
03852   unsigned int size = assertedExpr.size();
03853   unsigned int i;
03854 
03855   for (i = assertedExprCount; i < size; ++ i)
03856     //Update the value
03857     updateValue(assertedExpr[i][0], assertedExpr[i][1]);
03858 
03859   // Update the asserted count to be the size of the vector
03860   assertedExprCount = i;
03861 
03862 }
03863 
03864 void TheoryArithNew::updateDependenciesAdd(const Expr& var, const Expr& sum) {
03865   
03866   // Trace it
03867   TRACE("tableaux_dep", "updateDependenciesAdd(", var.toString() + ", ", sum.toString() + ")");
03868   
03869   // Go through the sum and add var to the dependencies of that term variable
03870   Expr::iterator term = sum.begin();
03871   Expr::iterator term_end = sum.end();
03872   for(; term != term_end; term ++)
03873     dependenciesMap[(*term)[1]].insert(var);
03874 
03875 }
03876 
03877 void TheoryArithNew::updateDependenciesRemove(const Expr& var, const Expr& sum) {
03878   
03879   // Trace it
03880   TRACE("tableaux_dep", "updateDependenciesRemove(", var.toString() + ", ", sum.toString() + ")");
03881     
03882   // Go through the sum and remove var to the dependencies of that term variable
03883   Expr::iterator term = sum.begin();
03884   Expr::iterator term_end = sum.end();
03885   for(; term != term_end; term ++)
03886     dependenciesMap[(*term)[1]].erase(var);
03887 
03888 }
03889 
03890 void TheoryArithNew::updateDependencies(const Expr& oldSum, const Expr& newSum, const Expr& dependentVar, const Expr& skipVar) {
03891 
03892   // Trace it
03893   TRACE("tableaux_dep", "updateDependencies(", oldSum.toString() + ", " + newSum.toString() + ", " + dependentVar.toString(), ")");
03894   
03895   // Since the sums are ordered by variables, we can just to a "merge sort"
03896   int oldSum_i = 0, newSum_i = 0;
03897   int oldSum_end = oldSum.arity(), newSum_end = newSum.arity();
03898   // Get the first variables
03899   while (oldSum_i < oldSum_end && newSum_i < newSum_end) {
03900     
03901     // Get the variable references
03902     const Expr oldVar = oldSum[oldSum_i][1];
03903     const Expr newVar = newSum[newSum_i][1];
03904     
03905     // If variables equal, just skip, everything is ok
03906     if (oldVar == newVar) {
03907       ++ oldSum_i; ++ newSum_i; continue; 
03908     } 
03909     
03910     // Otherwise do the work with the smaller one
03911     if (oldVar > newVar) {
03912       // Old variable has dissapeared, remove dependent from its list 
03913       if (oldVar != skipVar)
03914         dependenciesMap[oldVar].erase(dependentVar);
03915       // Move the old variable forward
03916       ++ oldSum_i; 
03917     } else { 
03918       // New variable has appeared, insert dependent to its list
03919       if (newVar != skipVar)
03920         dependenciesMap[newVar].insert(dependentVar);
03921       // Move the new variable forward
03922       ++ newSum_i;
03923     }
03924   } 
03925 
03926   // If there is leftovers in the old sum, just do the removals
03927   while (oldSum_i < oldSum_end) {
03928     // Get the var, and increase the index
03929     const Expr& var = oldSum[oldSum_i ++][1];
03930     // Update the dependency
03931     if (var != skipVar) 
03932       dependenciesMap[var].erase(dependentVar);
03933   }
03934   
03935   while (newSum_i < newSum_end) {
03936     // Get the var, and increase the index
03937     const Expr& var = newSum[newSum_i ++][1];
03938     // Update the dependency
03939     if (var != skipVar) 
03940       dependenciesMap[var].insert(dependentVar);
03941   }
03942 }
03943 
03944 void TheoryArithNew::registerAtom(const Expr& e) {
03945   
03946   // Trace it
03947   TRACE("propagate_arith", "registerAtom(", e.toString(), ")");
03948   TRACE("arith_atoms", "", e.toString(), "");
03949   
03950   // If it is a atomic formula, add it to the map 
03951   if (e.isAbsAtomicFormula()) {
03952     Expr rightSide    = e[1];
03953     int kind          = e.getKind();
03954     Rational leftSide = e[0].getRational();
03955     
03956     // The eps bound we'll be using
03957     EpsRational bound; 
03958     
03959     // Depending on the type of the inequality define the bound
03960     switch (kind) {
03961       case LT: 
03962         bound = EpsRational(leftSide, +1);
03963         break;          
03964       case LE:
03965         bound = leftSide;
03966         break;
03967       case GT: 
03968         bound = EpsRational(leftSide, -1);
03969         break;
03970       case GE:
03971         bound = leftSide;
03972         break;      
03973       default:
03974         // How did we get here
03975             FatalAssert(false, "TheoryArithNew::registerAtom: control should not reach here" + e.toString()); 
03976     }
03977     
03978     // Bound has been set, now add the
03979     allBounds.insert(ExprBoundInfo(bound, e));    
03980   } 
03981 
03982 //  // Printout the current set of atoms in the set
03983 //  cout << "ALL BOUNDS:" << endl;
03984 //  BoundInfoSet::iterator it = allBounds.begin();
03985 //  while (it != allBounds.end()) {
03986 //    cout << (*it).e << endl;
03987 //    ++ it;
03988 //  }
03989 }
03990 
03991 void TheoryArithNew::propagateTheory(const Expr& assertExpr, const EpsRational& bound, const EpsRational& oldBound) {
03992 
03993   // Trace it
03994   TRACE("propagate_arith", "propagateTheory(", assertExpr.toString() + ", " + bound.toString(), ")");
03995 
03996   // Make the bound info object, so that we can search for it
03997   ExprBoundInfo boundInfo(bound, assertExpr);
03998   
03999     // Get the exression on the right side hand
04000   Expr rightSide = assertExpr[1];
04001   
04002   // Get the kid of the disequality
04003   int kind = assertExpr.getKind();
04004   
04005   // Check wheather the kind is one of LT, LE, GT, GE
04006   DebugAssert(kind == LT || kind == LE || kind == GT || kind == GE , "TheoryArithNew::propagateTheory : expected an inequality");
04007   
04008   // If the bound is of the type LT or LE we go up
04009   if (kind == LT || kind == LE) {
04010     // Find the asserted fact in the set (it must be there)
04011     BoundInfoSet::iterator find      = allBounds.lower_bound(boundInfo);
04012     BoundInfoSet::iterator find_end  = allBounds.lower_bound(ExprBoundInfo(oldBound, assertExpr));
04013     
04014     // If we are at the begining, or not found, just exit
04015     if (find == find_end) return;
04016     
04017     // Now, go up until reached wrong right side (skip the first one, its the same as given)
04018     while (find != find_end) {
04019       
04020       // Go up;
04021       -- find;
04022     
04023       // Get the theorem of the find
04024       const Expr& findExpr = (*find).e;
04025       
04026       // Get the bound of the find
04027       const EpsRational findRat = (*find).bound; 
04028     
04029       // Get the kind of the expression in the theorem
04030       int findExprKind = findExpr.getKind();
04031       
04032       // Check if the right sides are the same
04033       if (rightSide != findExpr[1]) break;
04034     
04035       // Construct the theorem object
04036       Theorem lemma;
04037     
04038       // Check the type and equeue the lemma 
04039       if (findExprKind == LT || findExprKind == LE)
04040         // Imply the weaker inequality
04041         lemma = d_rules->implyWeakerInequality(assertExpr, findExpr);
04042       else
04043         // Imply the negation of the impossible inequality
04044         lemma = d_rules->implyNegatedInequality(assertExpr, findExpr);
04045         
04046     
04047       TRACE("propagate_arith", "lemma ==>", lemma.toString(), "");
04048       TRACE("arith_atoms", "Propagate: ", lemma.getExpr().toString(), "");
04049     
04050       // Put it across
04051       enqueueFact(lemma);
04052     }
04053   }  
04054   // If the bound is of the type GT or GE we go down
04055   else {
04056     // Find the asserted fact in the set (it must be there)
04057     BoundInfoSet::iterator find          = allBounds.upper_bound(boundInfo);
04058     BoundInfoSet::iterator find_end      = allBounds.upper_bound(ExprBoundInfo(oldBound, assertExpr));
04059     
04060     // Now, go down until reached wrong right side (skip the first one, its the same as given)
04061     while (find != find_end) {
04062               
04063       // Get the bound of the find
04064       const EpsRational findRat = (*find).bound; 
04065     
04066       // Get the expression in the theorem
04067       const Expr& findExpr = (*find).e;
04068       int findExprKind = findExpr.getKind();
04069       
04070       // Check if the right sides are the same
04071       if (rightSide != findExpr[1]) break;
04072     
04073       // Construct the theorem object
04074       Theorem lemma;
04075     
04076       // Check the type and equeue the lemma 
04077       if (findExprKind == GT || findExprKind == GE)
04078         // Imply the weaker inequality
04079         lemma = d_rules->implyWeakerInequality(assertExpr, findExpr);
04080       else
04081         // Imply the negation of the impossible inequality (use oposite than above)
04082         lemma = d_rules->implyNegatedInequality(assertExpr, findExpr);
04083             
04084       TRACE("propagate_arith", "lemma ==>", lemma.toString(), "");
04085       TRACE("arith_atoms", "Propagate: ", lemma.getExpr().toString(), "");
04086         
04087       // Put it across
04088       enqueueFact(lemma);
04089       
04090       // Go to the next one
04091       ++ find;
04092     }
04093   } 
04094 }
04095 
04096 Theorem TheoryArithNew::deriveGomoryCut(const Expr& x_i) {
04097 
04098   Theorem res;
04099 
04100   // CHECK IF APPLICABLE
04101   DebugAssert(isBasic(x_i), "TheoryArithNew::deriveGomoryCut variable must be a basic variable : " + x_i.toString()); 
04102   DebugAssert(intVariables.count(x_i) > 0, "TheoryArithNew::deriveGomoryCut variable must be a basic variable : " + x_i.toString());
04103 
04104   // Get the rational value of x_i
04105   Rational x_i_Value = getBeta(x_i).getRational();
04106   
04107   // Compute f_0
04108   Rational f_0 = x_i_Value - floor(x_i_Value);
04109     
04110   return res;
04111 }

Generated on Wed Nov 18 16:13:31 2009 for CVC3 by  doxygen 1.5.2