00001 /*****************************************************************************/ 00002 /*! 00003 * \file theory_arith_new.h 00004 * 00005 * Author: Dejan Jovanovic 00006 * 00007 * Created: Thu Jun 14 13:38:16 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 #ifndef _cvc3__include__theory_arith_new_h_ 00022 #define _cvc3__include__theory_arith_new_h_ 00023 00024 #include "theory_arith.h" 00025 00026 #include <hash_fun.h> 00027 #include <hash_map.h> 00028 #include <queryresult.h> 00029 #include <map> 00030 00031 namespace CVC3 { 00032 00033 00034 /** 00035 * This theory handles basic linear arithmetic. 00036 * 00037 * @author Clark Barrett 00038 * 00039 * @since Sat Feb 8 14:44:32 2003 00040 */ 00041 class TheoryArithNew :public TheoryArith { 00042 00043 /** For concrete model generation */ 00044 CDList<Theorem> d_diseq; 00045 /** Index to the next unprocessed disequality */ 00046 CDO<size_t> d_diseqIdx; 00047 ArithProofRules* d_rules; 00048 CDO<bool> d_inModelCreation; 00049 00050 /** Data class for the strongest free constant in separation inqualities **/ 00051 class FreeConst { 00052 private: 00053 Rational d_r; 00054 bool d_strict; 00055 public: 00056 FreeConst() { } 00057 FreeConst(const Rational& r, bool strict): d_r(r), d_strict(strict) { } 00058 const Rational& getConst() const { return d_r; } 00059 bool strict() const { return d_strict; } 00060 }; 00061 //! Printing 00062 friend std::ostream& operator<<(std::ostream& os, const FreeConst& fc); 00063 //! Private class for an inequality in the Fourier-Motzkin database 00064 class Ineq { 00065 private: 00066 Theorem d_ineq; //!< The inequality 00067 bool d_rhs; //!< Var is isolated on the RHS 00068 const FreeConst* d_const; //!< The max/min const for subsumption check 00069 //! Default constructor is disabled 00070 Ineq() { } 00071 public: 00072 //! Initial constructor. 'r' is taken from the subsumption database. 00073 Ineq(const Theorem& ineq, bool varOnRHS, const FreeConst& c): 00074 d_ineq(ineq), d_rhs(varOnRHS), d_const(&c) { } 00075 //! Get the inequality 00076 const Theorem& ineq() const { return d_ineq; } 00077 //! Get the max/min constant 00078 const FreeConst& getConst() const { return *d_const; } 00079 //! Flag whether var is isolated on the RHS 00080 bool varOnRHS() const { return d_rhs; } 00081 //! Flag whether var is isolated on the LHS 00082 bool varOnLHS() const { return !d_rhs; } 00083 //! Auto-cast to Theorem 00084 operator Theorem() const { return d_ineq; } 00085 }; 00086 //! Printing 00087 friend std::ostream& operator<<(std::ostream& os, const Ineq& ineq); 00088 //! Database of inequalities with a variable isolated on the right 00089 ExprMap<CDList<Ineq> *> d_inequalitiesRightDB; 00090 //! Database of inequalities with a variable isolated on the left 00091 ExprMap<CDList<Ineq> *> d_inequalitiesLeftDB; 00092 //! Mapping of inequalities to the largest/smallest free constant 00093 /*! The Expr is the original inequality with the free constant 00094 * removed and inequality converted to non-strict (for indexing 00095 * purposes). I.e. ax<c+t becomes ax<=t. This inequality is mapped 00096 * to a pair<c,strict>, the smallest (largest for c+t<ax) constant 00097 * among inequalities with the same 'a', 'x', and 't', and a boolean 00098 * flag indicating whether the strongest inequality is strict. 00099 */ 00100 CDMap<Expr, FreeConst> d_freeConstDB; 00101 // Input buffer to store the incoming inequalities 00102 CDList<Theorem> d_buffer; //!< Buffer of input inequalities 00103 CDO<size_t> d_bufferIdx; //!< Buffer index of the next unprocessed inequality 00104 const int* d_bufferThres; //!< Threshold when the buffer must be processed 00105 // Statistics for the variables 00106 /*! @brief Mapping of a variable to the number of inequalities where 00107 the variable would be isolated on the right */ 00108 CDMap<Expr, int> d_countRight; 00109 /*! @brief Mapping of a variable to the number of inequalities where 00110 the variable would be isolated on the left */ 00111 CDMap<Expr, int> d_countLeft; 00112 //! Set of shared terms (for counterexample generation) 00113 CDMap<Expr, bool> d_sharedTerms; 00114 //! Set of shared integer variables (i-leaves) 00115 CDMap<Expr, bool> d_sharedVars; 00116 //Directed Acyclic Graph representing partial variable ordering for 00117 //variable projection over inequalities. 00118 class VarOrderGraph { 00119 ExprMap<std::vector<Expr> > d_edges; 00120 ExprMap<bool> d_cache; 00121 bool dfs(const Expr& e1, const Expr& e2); 00122 public: 00123 void addEdge(const Expr& e1, const Expr& e2); 00124 //returns true if e1 < e2, false otherwise. 00125 bool lessThan(const Expr& e1, const Expr& e2); 00126 //selects those variables which are largest and incomparable among 00127 //v1 and puts it into v2 00128 void selectLargest(const std::vector<Expr>& v1, std::vector<Expr>& v2); 00129 //selects those variables which are smallest and incomparable among 00130 //v1, removes them from v1 and puts them into v2. 00131 void selectSmallest( std::vector<Expr>& v1, std::vector<Expr>& v2); 00132 00133 }; 00134 00135 VarOrderGraph d_graph; 00136 00137 // Private methods 00138 //! Check the term t for integrality. 00139 /*! \return a theorem of IS_INTEGER(t) or Null. */ 00140 Theorem isIntegerThm(const Expr& e); 00141 //! A helper method for isIntegerThm() 00142 /*! Check if IS_INTEGER(e) is easily derivable from the given 'thm' */ 00143 Theorem isIntegerDerive(const Expr& isIntE, const Theorem& thm); 00144 //! Check the term t for integrality (return bool) 00145 bool isInteger(const Expr& e) { return !(isIntegerThm(e).isNull()); } 00146 //! Check if the kids of e are fully simplified and canonized (for debugging) 00147 bool kidsCanonical(const Expr& e); 00148 00149 //! Canonize the expression e, assuming all children are canonical 00150 Theorem canon(const Expr& e); 00151 /*! @brief Canonize and reduce e w.r.t. union-find database; assume 00152 * all children are canonical */ 00153 Theorem canonSimplify(const Expr& e); 00154 /*! @brief Composition of canonSimplify(const Expr&) by 00155 * transitivity: take e0 = e1, canonize and simplify e1 to e2, 00156 * return e0 = e2. */ 00157 Theorem canonSimplify(const Theorem& thm) { 00158 return transitivityRule(thm, canonSimplify(thm.getRHS())); 00159 } 00160 //! Canonize predicate (x = y, x < y, etc.) 00161 Theorem canonPred(const Theorem& thm); 00162 //! Canonize predicate like canonPred except that the input theorem 00163 //! is an equivalent transformation. 00164 Theorem canonPredEquiv(const Theorem& thm); 00165 //! Solve an equation and return an equivalent Theorem in the solved form 00166 Theorem doSolve(const Theorem& e); 00167 //! takes in a conjunction equivalence Thm and canonizes it. 00168 Theorem canonConjunctionEquiv(const Theorem& thm); 00169 //! picks the monomial with the smallest abs(coeff) from the input 00170 //integer equation. 00171 Expr pickIntEqMonomial(const Expr& right); 00172 //! processes equalities with 1 or more vars of type REAL 00173 Theorem processRealEq(const Theorem& eqn); 00174 //! processes equalities whose vars are all of type INT 00175 Theorem processIntEq(const Theorem& eqn); 00176 //! One step of INT equality processing (aux. method for processIntEq()) 00177 Theorem processSimpleIntEq(const Theorem& eqn); 00178 //! Take an inequality and isolate a variable 00179 Theorem isolateVariable(const Theorem& inputThm, bool& e1); 00180 //! Update the statistics counters for the variable with a coeff. c 00181 void updateStats(const Rational& c, const Expr& var); 00182 //! Update the statistics counters for the monomial 00183 void updateStats(const Expr& monomial); 00184 //! Add an inequality to the input buffer. See also d_buffer 00185 void addToBuffer(const Theorem& thm); 00186 Expr pickMonomial(const Expr& right); 00187 public: // ArithTheoremProducer needs this function, so make it public 00188 //! Separate monomial e = c*p1*...*pn into c and 1*p1*...*pn 00189 void separateMonomial(const Expr& e, Expr& c, Expr& var); 00190 private: 00191 bool lessThanVar(const Expr& isolatedVar, const Expr& var2); 00192 //! Check if the term expression is "stale" 00193 bool isStale(const Expr& e); 00194 //! Check if the inequality is "stale" or subsumed 00195 bool isStale(const Ineq& ineq); 00196 void projectInequalities(const Theorem& theInequality,bool isolatedVarOnRHS); 00197 void assignVariables(std::vector<Expr>&v); 00198 void findRationalBound(const Expr& varSide, const Expr& ratSide, 00199 const Expr& var, 00200 Rational &r); 00201 bool findBounds(const Expr& e, Rational& lub, Rational& glb); 00202 00203 Theorem normalizeProjectIneqs(const Theorem& ineqThm1, 00204 const Theorem& ineqThm2); 00205 //! Take a system of equations and turn it into a solved form 00206 Theorem solvedForm(const std::vector<Theorem>& solvedEqs); 00207 /*! @brief Substitute all vars in term 't' according to the 00208 * substitution 'subst' and canonize the result. 00209 */ 00210 Theorem substAndCanonize(const Expr& t, ExprMap<Theorem>& subst); 00211 /*! @brief Substitute all vars in the RHS of the equation 'eq' of 00212 * the form (x = t) according to the substitution 'subst', and 00213 * canonize the result. 00214 */ 00215 Theorem substAndCanonize(const Theorem& eq, ExprMap<Theorem>& subst); 00216 //! Traverse 'e' and push all the i-leaves into 'vars' vector 00217 void collectVars(const Expr& e, std::vector<Expr>& vars, 00218 std::set<Expr>& cache); 00219 /*! @brief Check if alpha <= ax & bx <= beta is a finite interval 00220 * for integer var 'x', and assert the corresponding constraint 00221 */ 00222 void processFiniteInterval(const Theorem& alphaLEax, 00223 const Theorem& bxLEbeta); 00224 //! For an integer var 'x', find and process all constraints A <= ax <= A+c 00225 void processFiniteIntervals(const Expr& x); 00226 //! Recursive setup for isolated inequalities (and other new expressions) 00227 void setupRec(const Expr& e); 00228 00229 public: 00230 TheoryArithNew(TheoryCore* core); 00231 ~TheoryArithNew(); 00232 00233 // Trusted method that creates the proof rules class (used in constructor). 00234 // Implemented in arith_theorem_producer.cpp 00235 ArithProofRules* createProofRules(); 00236 00237 // Theory interface 00238 void addSharedTerm(const Expr& e); 00239 void assertFact(const Theorem& e); 00240 void refineCounterExample(); 00241 void computeModelBasic(const std::vector<Expr>& v); 00242 void computeModel(const Expr& e, std::vector<Expr>& vars); 00243 void checkSat(bool fullEffort); 00244 Theorem rewrite(const Expr& e); 00245 void setup(const Expr& e); 00246 void update(const Theorem& e, const Expr& d); 00247 Theorem solve(const Theorem& e); 00248 void checkAssertEqInvariant(const Theorem& e); 00249 void checkType(const Expr& e); 00250 void computeType(const Expr& e); 00251 Type computeBaseType(const Type& t); 00252 void computeModelTerm(const Expr& e, std::vector<Expr>& v); 00253 Expr computeTypePred(const Type& t, const Expr& e); 00254 Expr computeTCC(const Expr& e); 00255 ExprStream& print(ExprStream& os, const Expr& e); 00256 virtual Expr parseExprOp(const Expr& e); 00257 00258 // DDDDDDDDDDDDDDDDDDDDDDDDEEEEEEEEEEEEEEEEEEEEEEEJJJJJJJJJJJJJJJJJJJJJAAAAAAAAAAAAAAAAAAAAAAANNNNNNNNNNNNNNNNNNNNNNN 00259 00260 public: 00261 00262 /** 00263 * EpsRational class ecapsulates the rationals with a symbolic small \f$\epsilon\f$ added. Each rational 00264 * number is presented as a pair \f$(q, k) = q + k\epsilon\f$, where \f$\epsilon\f$ is treated symbolically. 00265 * The operations on the new rationals are defined as 00266 * <ul> 00267 * <li>\f$(q_1, k_1) + (q_2, k_2) \equiv (q_1 + q_2, k_1 + k_2)\f$ 00268 * <li>\f$a \times (q, k) \equiv (a \times q, a \times k)\f$ 00269 * <li>\f$(q_1, k_1) \leq (q_2, k_2) \equiv (q_1 < q_2) \vee (q_1 = q_2 \wedge k_1 \leq k_2)\f$ 00270 * </ul> 00271 * 00272 * Note that the operations on the infinite values are not defined, as they are never used currently. Infinities can 00273 * only be asigned or compared. 00274 */ 00275 class EpsRational { 00276 00277 protected: 00278 00279 /** Type of rationals, normal and the two infinities */ 00280 typedef enum { FINITE, PLUS_INFINITY, MINUS_INFINITY } RationalType; 00281 00282 /** The type of this rational */ 00283 RationalType type; 00284 00285 /** The rational part */ 00286 Rational q; 00287 00288 /** The epsilon multiplier */ 00289 Rational k; 00290 00291 /** 00292 * Private constructor to construt infinities. 00293 */ 00294 EpsRational(RationalType type) : type(type) {} 00295 00296 public: 00297 00298 /** 00299 * Returns if the number is a plain rational. 00300 * 00301 * @return true if rational, false otherwise 00302 */ 00303 inline bool isRational() const { return k == 0; } 00304 00305 /** 00306 * Returns if the number is a plain integer. 00307 * 00308 * @return true if rational, false otherwise 00309 */ 00310 inline bool isInteger() const { return k == 0 && q.isInteger(); } 00311 00312 /** 00313 * Returns the floor of the number \f$x = q + k \epsilon\f$ using the following fomula 00314 * \f[ 00315 * \lfloor \beta(x) \rfloor = 00316 * \begin{cases} 00317 * \lfloor q \rfloor & \text{ if } q \notin Z\\ 00318 * q & \text{ if } q \in Z \text{ and } k \geq 0\\ 00319 * q - 1 & \text{ if } q \in Z \text{ and } k < 0 00320 * \end{cases} 00321 * \f] 00322 */ 00323 inline Rational getFloor() const { 00324 if (q.isInteger()) { 00325 if (k >= 0) return q; 00326 else return q - 1; 00327 } else 00328 // If not an integer, just floor it 00329 return floor(q); 00330 } 00331 00332 00333 /** 00334 * Returns the rational part of the number 00335 * 00336 * @return the rational 00337 */ 00338 inline Rational getRational() const { return q; } 00339 00340 /** The infinity constant */ 00341 static const EpsRational PlusInfinity; 00342 /** The negative infinity constant */ 00343 static const EpsRational MinusInfinity; 00344 /** The zero constant */ 00345 static const EpsRational Zero; 00346 00347 00348 /** The blank constructor */ 00349 EpsRational() : type(FINITE), q(0), k(0) {} 00350 00351 /** Copy constructor */ 00352 EpsRational(const EpsRational& r) : type(r.type), q(r.q), k(r.k) {} 00353 00354 /** 00355 * Constructor from a rational, constructs a new pair (q, 0). 00356 * 00357 * @param q the rational 00358 */ 00359 EpsRational(const Rational q) : type(FINITE), q(q), k(0) {} 00360 00361 /** 00362 * Constructor from a rational and a given epsilon multiplier, constructs a 00363 * new pair (q, k). 00364 * 00365 * @param q the rational 00366 * @param k the epsilon multiplier 00367 */ 00368 EpsRational(const Rational q, const Rational k) : type(FINITE), q(q), k(k) {} 00369 00370 /** 00371 * Addition operator for two EpsRational numbers. 00372 * 00373 * @param r the number to be added 00374 * @return the sum as defined in the class 00375 */ 00376 inline EpsRational operator + (const EpsRational& r) const { 00377 DebugAssert(type == FINITE, "EpsRational::operator +, adding to infinite number"); 00378 DebugAssert(r.type == FINITE, "EpsRational::operator +, adding an infinite number"); 00379 return EpsRational(q + r.q, k + r.k); 00380 } 00381 00382 /** 00383 * Addition operator for two EpsRational numbers. 00384 * 00385 * @param r the number to be added 00386 * @return the sum as defined in the class 00387 */ 00388 inline EpsRational& operator += (const EpsRational& r) { 00389 DebugAssert(type == FINITE, "EpsRational::operator +, adding to infinite number"); 00390 q = q + r.q; 00391 k = k + r.k; 00392 return *this; 00393 } 00394 00395 /** 00396 * Subtraction operator for two EpsRational numbers. 00397 * 00398 * @param r the number to be added 00399 * @return the sum as defined in the class 00400 */ 00401 inline EpsRational operator - (const EpsRational& r) const { 00402 DebugAssert(type == FINITE, "EpsRational::operator -, subtracting from infinite number"); 00403 DebugAssert(r.type == FINITE, "EpsRational::operator -, subtracting an infinite number"); 00404 return EpsRational(q - r.q, k - r.k); 00405 } 00406 00407 /** 00408 * Multiplication operator EpsRational number and a rational number. 00409 * 00410 * @param a the number to be multiplied 00411 * @return the product as defined in the class 00412 */ 00413 inline EpsRational operator * (const Rational& a) const { 00414 DebugAssert(type == FINITE, "EpsRational::operator *, multiplying an infinite number"); 00415 return EpsRational(a * q, a * k); 00416 } 00417 00418 /** 00419 * Division operator EpsRational number and a rational number. 00420 * 00421 * @param a the number to be multiplied 00422 * @return the product as defined in the class 00423 */ 00424 inline EpsRational operator / (const Rational& a) const { 00425 DebugAssert(type == FINITE, "EpsRational::operator *, dividing an infinite number"); 00426 return EpsRational(q / a, k / a); 00427 } 00428 00429 /** 00430 * Equality comparison operator. 00431 */ 00432 inline bool operator == (const EpsRational& r) const { return (q == r.q && k == r.k); } 00433 00434 /** 00435 * Les then or equal comparison operator. 00436 */ 00437 inline bool operator <= (const EpsRational& r) const { 00438 switch (r.type) { 00439 case FINITE: 00440 if (type == FINITE) 00441 // Normal comparison 00442 return (q < r.q || (q == r.q && k <= r.k)); 00443 else 00444 // Finite number is bigger only of the negative infinity 00445 return type == MINUS_INFINITY; 00446 case PLUS_INFINITY: 00447 // Everything is less then or equal than +inf 00448 return true; 00449 case MINUS_INFINITY: 00450 // Only -inf is less then or equal than -inf 00451 return (type == MINUS_INFINITY); 00452 default: 00453 // Ohohohohohoooooo, whats up 00454 FatalAssert(false, "EpsRational::operator <=, what kind of number is this????"); 00455 } 00456 return false; 00457 } 00458 00459 /** 00460 * Les then comparison operator. 00461 */ 00462 inline bool operator < (const EpsRational& r) const { return !(r <= *this); } 00463 00464 /** 00465 * Bigger then equal comparison operator. 00466 */ 00467 inline bool operator > (const EpsRational& r) const { return !(*this <= r); } 00468 00469 /** 00470 * Returns the string representation of the number. 00471 * 00472 * @param the string representation of the number 00473 */ 00474 std::string toString() const { 00475 switch (type) { 00476 case FINITE: 00477 return "(" + q.toString() + ", " + k.toString() + ")"; 00478 case PLUS_INFINITY: 00479 return "+inf"; 00480 case MINUS_INFINITY: 00481 return "-inf"; 00482 default: 00483 FatalAssert(false, "EpsRational::toString, what kind of number is this????"); 00484 } 00485 return "hm, what am I?"; 00486 } 00487 }; 00488 00489 /** 00490 * Registers the atom given from the core. This atoms are stored so that they can be used 00491 * for theory propagation. 00492 * 00493 * @param e the expression (atom) that is part of the input formula 00494 */ 00495 void registerAtom(const Expr& e); 00496 00497 private: 00498 00499 /** A set of all integer variables */ 00500 std::set<Expr> intVariables; 00501 00502 /** 00503 * Return a Gomory cut plane derivation of the variable $x_i$. Mixed integer 00504 * Gomory cut can be constructed if 00505 * <ul> 00506 * <li>\f$x_i\f$ is a integer basic variable with a non-integer value 00507 * <li>all non-basic variables in the row of \f$x_i\f$ are assigned to their 00508 * upper or lower bounds 00509 * <li>all the values on the right side of the row have rational values (non 00510 * eps-rational values) 00511 * </ul> 00512 */ 00513 Theorem deriveGomoryCut(const Expr& x_i); 00514 00515 /** 00516 * Tries to rafine the integer constraint of the theorem. For example, 00517 * x < 1 is rewritten as x <= 0, and x <(=) 1.5 is rewritten as x <= 1. 00518 * The constraint should be in the normal form. 00519 * 00520 * @param thm the derivation of the constraint 00521 */ 00522 Theorem rafineIntegerConstraints(const Theorem& thm); 00523 00524 /** Are we consistent or not */ 00525 CDO<QueryResult> consistent; 00526 00527 /** The theorem explaining the inconsistency */ 00528 Theorem explanation; 00529 00530 /** 00531 * The structure necessaty to hold the bounds. 00532 */ 00533 struct BoundInfo { 00534 /** The bound itself */ 00535 EpsRational bound; 00536 /** The assertion theoreem of the bound */ 00537 Theorem theorem; 00538 00539 /** Constructor */ 00540 BoundInfo(const EpsRational& bound, const Theorem& thm): bound(bound), theorem(thm) {} 00541 00542 /** The empty constructor for the map */ 00543 BoundInfo(): bound(0), theorem() {} 00544 00545 /** 00546 * The comparator, just if we need it. Compares first by expressions then by bounds 00547 */ 00548 bool operator < (const BoundInfo& bI) const { 00549 // Get tje expressoins 00550 const Expr& expr1 = (theorem.isRewrite() ? theorem.getRHS() : theorem.getExpr()); 00551 const Expr& expr2 = (bI.theorem.isRewrite() ? bI.theorem.getRHS() : bI.theorem.getExpr()); 00552 00553 std::cout << expr1 << " @ " << expr2 << std::endl; 00554 00555 // Compare first by the expressions (right sides of expressions) 00556 if (expr1[1] == expr2[1]) 00557 // If the same, just return the bound comparison (plus a trick to order equal bounds, different relations) 00558 if (bound == bI.bound && expr1.getKind() != expr2.getKind()) 00559 return expr1.getKind() == LE; // LE before GE -- only case that can happen 00560 else 00561 return bound < bI.bound; 00562 else 00563 // Return the expression comparison 00564 return expr1[1] < expr2[1]; 00565 } 00566 }; 00567 00568 00569 /** 00570 * The structure necessaty to hold the bounds on expressions (for theory propagation). 00571 */ 00572 struct ExprBoundInfo { 00573 /** The bound itself */ 00574 EpsRational bound; 00575 /** The assertion theoreem of the bound */ 00576 Expr e; 00577 00578 /** Constructor */ 00579 ExprBoundInfo(const EpsRational& bound, const Expr& e): bound(bound), e(e) {} 00580 00581 /** The empty constructor for the map */ 00582 ExprBoundInfo(): bound(0) {} 00583 00584 /** 00585 * The comparator, just if we need it. Compares first by expressions then by bounds 00586 */ 00587 bool operator < (const ExprBoundInfo& bI) const { 00588 00589 // Compare first by the expressions (right sides of expressions) 00590 if (e[1] == bI.e[1]) 00591 // If the same, just return the bound comparison (plus a trick to order equal bounds, different relations) 00592 if (bound == bI.bound && e.getKind() != bI.e.getKind()) 00593 return e.getKind() == LE; // LE before GE -- only case that can happen 00594 else 00595 return bound < bI.bound; 00596 else 00597 // Return the expression comparison 00598 return e[1] < bI.e[1]; 00599 } 00600 }; 00601 00602 /** The map from variables to lower bounds (these must be backtrackable) */ 00603 CDMap<Expr, BoundInfo> lowerBound; 00604 /** The map from variables to upper bounds (these must be backtrackable) */ 00605 CDMap<Expr, BoundInfo> upperBound; 00606 /** The current real valuation of the variables (these must be backtrackable for the last succesefull checkSAT!!!) */ 00607 CDMap<Expr, EpsRational> beta; 00608 00609 typedef Hash::hash_map<Expr, Theorem> TebleauxMap; 00610 //typedef google::sparse_hash_map<Expr, Theorem, Hash::hash<Expr> > TebleauxMap; 00611 //typedef std::map<Expr, Theorem> TebleauxMap; 00612 00613 typedef std::set<Expr> SetOfVariables; 00614 typedef Hash::hash_map<Expr, SetOfVariables> DependenciesMap; 00615 00616 /** Maps variables to sets of variables that depend on it in the tableaux */ 00617 DependenciesMap dependenciesMap; 00618 00619 /** The tableaux, a map from basic variables to the expressions over the non-basic ones (theorems that explain them how we got there) */ 00620 TebleauxMap tableaux; 00621 00622 /** Additional tableaux map from expressions asserted to the corresponding theorems explaining the introduction of the new variables */ 00623 TebleauxMap freshVariables; 00624 00625 /** A set containing all the unsatisfied basic variables */ 00626 std::set<Expr> unsatBasicVariables; 00627 00628 /** The vector to keep the assignments from fresh variables to expressions they represent */ 00629 std::vector<Expr> assertedExpr; 00630 /** The backtrackable number of fresh variables asserted so far */ 00631 CDO<unsigned int> assertedExprCount; 00632 00633 /** A set of BoundInfo objects */ 00634 typedef std::set<ExprBoundInfo> BoundInfoSet; 00635 00636 /** Internal variable to see wheather to propagate or not */ 00637 bool propagate; 00638 00639 /** 00640 * Propagate all that is possible from given assertion and its bound 00641 */ 00642 void propagateTheory(const Expr& assertExpr, const EpsRational& bound, const EpsRational& oldBound); 00643 00644 /** 00645 * Store all the atoms from the formula in this set. It is searchable by an expression 00646 * and the bound. To get all the implied atoms, one just has to go up (down) and check if the 00647 * atom or it's negation are implied. 00648 */ 00649 BoundInfoSet allBounds; 00650 00651 /** 00652 * Adds var to the dependencies sets of all the variables in the sum. 00653 * 00654 * @param var the variable on the left side 00655 * @param the sum that defines the variable 00656 */ 00657 void updateDependenciesAdd(const Expr& var, const Expr& sum); 00658 00659 /** 00660 * Remove var from the dependencies sets of all the variables in the sum. 00661 * 00662 * @param var the variable on the left side 00663 * @param the sum that defines the variable 00664 */ 00665 void updateDependenciesRemove(const Expr& var, const Expr& sum); 00666 00667 /** 00668 * Updates the dependencies if a right side of an expression in the tableaux is changed. For example, 00669 * if oldExpr is x + y and newExpr is y + z, var will be added to the dependency list of z, and removed 00670 * from the dependency list of x. 00671 * 00672 * @param oldExpr the old right side of the tableaux 00673 * @param newExpr the new right side of the tableaux 00674 * @param var the variable that is defined by these two expressions 00675 * @param var a variable to skip when going through the expressions 00676 */ 00677 void updateDependencies(const Expr& oldExpr, const Expr& newExpr, const Expr& var, const Expr& skipVar); 00678 00679 /** 00680 * Update the values of variables that have appeared in the tableaux due to backtracking. 00681 */ 00682 void updateFreshVariables(); 00683 00684 /** 00685 * Updates the value of variable var by computing the value of expression e. 00686 * 00687 * @param var the variable to update 00688 * @param e the expression to compute 00689 */ 00690 void updateValue(const Expr& var, const Expr& e); 00691 00692 /** 00693 * Returns a string representation of the tableaux. 00694 * 00695 * @return tableaux as string 00696 */ 00697 std::string tableauxAsString() const; 00698 00699 /** 00700 * Returns a string representation of the unsat variables. 00701 * 00702 * @return unsat as string 00703 */ 00704 std::string unsatAsString() const; 00705 00706 /** 00707 * Returns a string representation of the current bounds. 00708 * 00709 * @return tableaux as string 00710 */ 00711 std::string boundsAsString(); 00712 00713 /** 00714 * Gets the equality of the fresh variable tableaux variable corresponding to this expression. If the expression has already been 00715 * asserted, the coresponding variable is returned, othervise a fresh variable is created and the theorem is returned. 00716 * 00717 * @param leftSide the left side of the asserted constraint 00718 * @return the equality theorem s = leftSide 00719 */ 00720 Theorem getVariableIntroThm(const Expr& leftSide); 00721 00722 /** 00723 * Find the coefficient standing by the variable var in the expression expr. Expresion is expected to be 00724 * in canonical form, i.e either a rational constant, an arithmetic leaf (i.e. variable or term from some 00725 * other theory), (MULT rat leaf) where rat is a non-zero rational constant, leaf is an arithmetic leaf or 00726 * (PLUS \f$const term_0 term_1 ... term_n\f$) where each \f$term_i\f$ is either a leaf or (MULT \f$rat leaf\f$) 00727 * and each leaf in \f$term_i\f$ must be strictly greater than the leaf in \f$term_{i+1}\f$. 00728 * 00729 * @param var the variable 00730 * @param expr the expression to search in 00731 */ 00732 const Rational& findCoefficient(const Expr& var, const Expr& expr); 00733 00734 /** 00735 * Return true iof the given variable is basic in the tableaux, i.e. it is on the left side, expressed 00736 * in terms of the non-basic variables. 00737 * 00738 * @param x the variable to be checked 00739 * @return true if the variable is basic, false if the variable is non-basic 00740 */ 00741 bool isBasic(const Expr& x) const; 00742 00743 /** 00744 * Returns the coefficient at a_ij in the current tableaux, i.e. the coefficient 00745 * at x_j in the row of x_i. 00746 * 00747 * @param x_i a basic variable 00748 * @param x_j a non-basic variable 00749 * @return the reational coefficient 00750 */ 00751 Rational getTableauxEntry(const Expr& x_i, const Expr& x_j); 00752 00753 /** 00754 * Swaps a basic variable \f$x_r\f$ and a non-basic variable \f$x_s\f$ such 00755 * that ars \f$a_{rs} \neq 0\f$. After pivoting, \f$x_s\f$ becomes basic and \f$x_r\f$ becomes non-basic. 00756 * The tableau is updated by replacing equation \f[x_r = \sum_{x_j \in N}{a_{rj}xj}\f] with 00757 * \f[x_s = \frac{x_r}{a_{rs}} - \sum_{x_j \in N }{\frac{a_{rj}}{a_rs}x_j}\f] and this equation 00758 * is used to eliminate \f$x_s\f$ from the rest of the tableau by substitution. 00759 * 00760 * @param x_r a basic variable 00761 * @param x_s a non-basic variable 00762 */ 00763 void pivot(const Expr& x_r, const Expr& x_s); 00764 00765 /** 00766 * Sets the value of a non-basic variable \f$x_i\f$ to \f$v\f$ and adjusts the value of all 00767 * the basic variables so that all equations remain satisfied. 00768 * 00769 * @param x_i a non-basic variable 00770 * @param v the value to set the variable \f$x_i\f$ to 00771 */ 00772 void update(const Expr& x_i, const EpsRational& v); 00773 00774 /** 00775 * Pivots the basic variable \f$x_i\f$ and the non-basic variable \f$x_j\f$. It also sets \f$x_i\f$ to \f$v\f$ and adjusts all basic 00776 * variables to keep the equations satisfied. 00777 * 00778 * @param x_i a basic variable 00779 * @param x_j a non-basic variable 00780 * @param v the valie to assign to x_i 00781 */ 00782 void pivotAndUpdate(const Expr& x_i, const Expr& x_j, const EpsRational& v); 00783 00784 /** 00785 * Asserts a new upper bound constraint on a variable and performs a simple check for consistency (not complete). 00786 * 00787 * @param x_i the variable to assert the bound on 00788 */ 00789 QueryResult assertUpper(const Expr& x_i, const EpsRational& c, const Theorem& thm); 00790 00791 /** 00792 * Asserts a new lower bound constraint on a variable and performs a simple check for consistency (not complete). 00793 * 00794 * @param x_i the variable to assert the bound on 00795 */ 00796 QueryResult assertLower(const Expr& x_i, const EpsRational& c, const Theorem& thm); 00797 00798 /** 00799 * Asserts a new equality constraint on a variable by asserting both upper and lower bound. 00800 * 00801 * @param x_i the variable to assert the bound on 00802 */ 00803 QueryResult assertEqual(const Expr& x_i, const EpsRational& c, const Theorem& thm); 00804 00805 /** 00806 * Type of noramlization GCD = 1 or just first coefficient 1 00807 */ 00808 typedef enum { NORMALIZE_GCD, NORMALIZE_UNIT } NormalizationType; 00809 00810 /** 00811 * Given a canonized term, compute a factor to make all coefficients integer and relatively prime 00812 */ 00813 Expr computeNormalFactor(const Expr& rhs, NormalizationType type = NORMALIZE_GCD); 00814 00815 /** 00816 * Normalize an equation (make all coefficients rel. prime integers) 00817 */ 00818 Theorem normalize(const Expr& e, NormalizationType type = NORMALIZE_GCD); 00819 00820 /** 00821 * Normalize an equation (make all coefficients rel. prime integers) accepts a rewrite theorem over 00822 * eqn|ineqn and normalizes it and returns a theorem to that effect. 00823 */ 00824 Theorem normalize(const Theorem& thm, NormalizationType type = NORMALIZE_GCD); 00825 00826 /** 00827 * Canonise the equation using the tebleaux equations, i.e. replace all the tableaux right sides 00828 * with the corresponding left sides and canonise the result. 00829 * 00830 * @param eq the equation to canonise 00831 * @return the explaining theorem 00832 */ 00833 Theorem substAndCanonizeModTableaux(const Theorem& eq); 00834 00835 /** 00836 * Canonise the sum using the tebleaux equations, i.e. replace all the tableaux right sides 00837 * with the corresponding left sides and canonise the result. 00838 * 00839 * @param sum the canonised sum to canonise 00840 * @param the explaining theorem 00841 */ 00842 Theorem substAndCanonizeModTableaux(const Expr& sum); 00843 00844 /** 00845 * Sustitute the given equation everywhere in the tableaux. 00846 * 00847 * @param eq the equation to use for substitution 00848 * @return the explaining theorem 00849 */ 00850 void substAndCanonizeTableaux(const Theorem& eq); 00851 00852 /** 00853 * Given an equality eq: \f$\sum a_i x_i = y\f$ and a variable $var$ that appears in 00854 * on the left hand side, pivots $y$ and $var$ so that $y$ comes to the right-hand 00855 * side. 00856 * 00857 * @param eq the proof of the equality 00858 * @param var the variable to move to the right-hand side 00859 */ 00860 Theorem pivotRule(const Theorem& eq, const Expr& var); 00861 00862 /** 00863 * Knowing that the tableaux row for \f$x_i\f$ is the problematic one, generate the 00864 * explanation clause. The variables in the row of \f$x_i = \sum_{x_j \in \mathcal{N}}{a_ij x_j}\f$ are separatied to 00865 * <ul> 00866 * <li>\f$\mathcal{N}^+ = \left\lbrace x_j \in \mathcal{N} \; | \; a_{ij} > 0 \right\rbrace\f$ 00867 * <li>\f$\mathcal{N}^- = \left\lbrace x_j \in \mathcal{N} \; | \; a_{ij} < 0\right\rbrace\f$ 00868 * </ul> 00869 * Then, the explanation clause to be returned is 00870 * \f[\Gamma = \left\lbrace x_j \leq u_j \; | \; x_j \in \mathcal{N}^+\right\rbrace \cup \left\lbrace l_j \leq x_j \; | \; 00871 * x_j \in \mathcal{N}^-\right\rbrace \cup \left\lbrace l_i \leq x_i \right\rbrace\f] 00872 * 00873 * @param var the variable that caused the clash 00874 * @return the theorem explainang the clash 00875 */ 00876 Theorem getLowerBoundExplanation(const TebleauxMap::iterator& var_it); 00877 00878 /** 00879 * Knowing that the tableaux row for \f$x_i\f$ is the problematic one, generate the 00880 * explanation clause. The variables in the row of \f$x_i = \sum_{x_j \in \mathcal{N}}{a_ij x_j}\f$ are separatied to 00881 * <ul> 00882 * <li>\f$\mathcal{N}^+ = \left\lbrace x_j \in \mathcal{N} \; | \; a_{ij} > 0 \right\rbrace\f$ 00883 * <li>\f$\mathcal{N}^- = \left\lbrace x_j \in \mathcal{N} \; | \; a_{ij} < 0\right\rbrace\f$ 00884 * </ul> 00885 * Then, the explanation clause to be returned is 00886 * \f[\Gamma = \left\lbrace x_j \leq u_j \; | \; x_j \in \mathcal{N}^-\right\rbrace \cup \left\lbrace l_j \leq x_j \; | \; 00887 * x_j \in \mathcal{N}^+\right\rbrace \cup \left\lbrace x_i \leq u_i \right\rbrace\f] 00888 * 00889 * @param var the variable that caused the clash 00890 * @return the theorem explainang the clash 00891 */ 00892 Theorem getUpperBoundExplanation(const TebleauxMap::iterator& var_it); 00893 00894 Theorem addInequalities(const Theorem& le_1, const Theorem& le_2); 00895 00896 /** 00897 * Check the satisfiability 00898 */ 00899 QueryResult checkSatSimplex(); 00900 00901 /** 00902 * Check the satisfiability of integer constraints 00903 */ 00904 QueryResult checkSatInteger(); 00905 00906 /** 00907 * The last lemma that we asserted to check the integer satisfiability. We don't do checksat until 00908 * the lemma split has been asserted. 00909 */ 00910 CDO<Theorem> integer_lemma; 00911 00912 public: 00913 00914 /** 00915 * Gets the current lower bound on variable x. 00916 * 00917 * @param x the variable 00918 * @return the current lower bound on x 00919 */ 00920 EpsRational getLowerBound(const Expr& x) const; 00921 00922 /** 00923 * Get the current upper bound on variable x. 00924 * 00925 * @param x the variable 00926 * @return the current upper bound on x 00927 */ 00928 EpsRational getUpperBound(const Expr& x) const; 00929 00930 /** 00931 * Gets the theorem of the current lower bound on variable x. 00932 * 00933 * @param x the variable 00934 * @return the current lower bound on x 00935 */ 00936 Theorem getLowerBoundThm(const Expr& x) const; 00937 00938 /** 00939 * Get the theorem of the current upper bound on variable x. 00940 * 00941 * @param x the variable 00942 * @return the current upper bound on x 00943 */ 00944 Theorem getUpperBoundThm(const Expr& x) const; 00945 00946 /** 00947 * Gets the current valuation of variable x (beta). 00948 * 00949 * @param x the variable 00950 * @return the current value of variable x 00951 */ 00952 EpsRational getBeta(const Expr& x); 00953 00954 // DDDDDDDDDDDDDDDDDDDDDDDDEEEEEEEEEEEEEEEEEEEEEEEJJJJJJJJJJJJJJJJJJJJJAAAAAAAAAAAAAAAAAAAAAAANNNNNNNNNNNNNNNNNNNNNNN 00955 00956 }; 00957 00958 } 00959 00960 #endif