00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022 #include "theory_arith_old.h"
00023 #include "arith_proof_rules.h"
00024
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 #include "../theory_core/core_proof_rules.h"
00034
00035
00036 using namespace std;
00037 using namespace CVC3;
00038
00039
00040
00041
00042
00043
00044 namespace CVC3 {
00045
00046 ostream& operator<<(ostream& os, const TheoryArithOld::FreeConst& fc) {
00047 os << "FreeConst(r=" << fc.getConst() << ", "
00048 << (fc.strict()? "strict" : "non-strict") << ")";
00049 return os;
00050 }
00051
00052
00053
00054
00055
00056 ostream& operator<<(ostream& os, const TheoryArithOld::Ineq& ineq) {
00057 os << "Ineq(" << ineq.ineq().getExpr() << ", isolated on "
00058 << (ineq.varOnRHS()? "RHS" : "LHS") << ", const = "
00059 << ineq.getConst() << ")";
00060 return os;
00061 }
00062 }
00063
00064
00065
00066
00067
00068
00069
00070 Theorem TheoryArithOld::isIntegerThm(const Expr& e) {
00071
00072 Type t = e.getType();
00073 if (isReal(t)) return Theorem();
00074 if (isInt(t)) return typePred(e);
00075
00076
00077 return isIntegerDerive(Expr(IS_INTEGER, e), typePred(e));
00078 }
00079
00080
00081 Theorem TheoryArithOld::isIntegerDerive(const Expr& isIntE, const Theorem& thm) {
00082 const Expr& e = thm.getExpr();
00083
00084 if(e == isIntE) return thm;
00085
00086 Theorem res;
00087
00088 if(e.isAnd()) {
00089 int i, iend=e.arity();
00090 for(i=0; i<iend; ++i) {
00091 res = isIntegerDerive(isIntE, getCommonRules()->andElim(thm, i));
00092 if(!res.isNull()) return res;
00093 }
00094 }
00095 return res;
00096 }
00097
00098 const Rational& TheoryArithOld::freeConstIneq(const Expr& ineq, bool varOnRHS) {
00099 DebugAssert(isIneq(ineq), "TheoryArithOld::freeConstIneq("+ineq.toString()+")");
00100 const Expr& e = varOnRHS? ineq[0] : ineq[1];
00101
00102 switch(e.getKind()) {
00103 case PLUS:
00104 return e[0].getRational();
00105 case RATIONAL_EXPR:
00106 return e.getRational();
00107 default: {
00108 static Rational zero(0);
00109 return zero;
00110 }
00111 }
00112 }
00113
00114
00115 const TheoryArithOld::FreeConst&
00116 TheoryArithOld::updateSubsumptionDB(const Expr& ineq, bool varOnRHS,
00117 bool& subsumed) {
00118 TRACE("arith ineq", "TheoryArithOld::updateSubsumptionDB(", ineq,
00119 ", var isolated on "+string(varOnRHS? "RHS" : "LHS")+")");
00120 DebugAssert(isLT(ineq) || isLE(ineq), "TheoryArithOld::updateSubsumptionDB("
00121 +ineq.toString()+")");
00122
00123 Expr index;
00124 const Expr& t = varOnRHS? ineq[0] : ineq[1];
00125 bool strict(isLT(ineq));
00126 Rational c(0);
00127 if(isPlus(t)) {
00128 DebugAssert(t.arity() >= 2, "TheoryArithOld::updateSubsumptionDB("
00129 +ineq.toString()+")");
00130 c = t[0].getRational();
00131 Expr newT;
00132 if(t.arity() == 2) {
00133 newT = t[1];
00134 } else {
00135 vector<Expr> kids;
00136 Expr::iterator i=t.begin(), iend=t.end();
00137 kids.push_back(rat(0));
00138 for(++i; i!=iend; ++i) kids.push_back(*i);
00139 DebugAssert(kids.size() > 0, "kids.size = "+int2string(kids.size())
00140 +", ineq = "+ineq.toString());
00141 newT = plusExpr(kids);
00142 }
00143 if(varOnRHS)
00144 index = leExpr(rat(0), canonSimplify(ineq[1] - newT).getRHS());
00145 else
00146 index = leExpr(canonSimplify(ineq[0]-newT).getRHS(), rat(0));
00147 } else if(isRational(t)) {
00148 c = t.getRational();
00149 if(varOnRHS)
00150 index = leExpr(rat(0), ineq[1]);
00151 else
00152 index = leExpr(ineq[0], rat(0));
00153 } else if(isLT(ineq))
00154 index = leExpr(ineq[0], ineq[1]);
00155 else
00156 index = ineq;
00157
00158 CDMap<Expr, FreeConst>::iterator i=d_freeConstDB.find(index),
00159 iend=d_freeConstDB.end();
00160 if(i == iend) {
00161 subsumed = false;
00162
00163 CDOmap<Expr,FreeConst>& obj = d_freeConstDB[index];
00164 obj = FreeConst(c,strict);
00165 TRACE("arith ineq", "freeConstDB["+index.toString()+"] := ", obj, "");
00166 return obj.get();
00167 } else {
00168 CDOmap<Expr,FreeConst>& obj = d_freeConstDB[index];
00169 const FreeConst& fc = obj.get();
00170 if(varOnRHS) {
00171 subsumed = (c < fc.getConst() ||
00172 (c == fc.getConst() && (!strict || fc.strict())));
00173 } else {
00174 subsumed = (c > fc.getConst() ||
00175 (c == fc.getConst() && (strict || !fc.strict())));
00176 }
00177 if(!subsumed) {
00178 obj = FreeConst(c,strict);
00179 TRACE("arith ineq", "freeConstDB["+index.toString()+"] := ", obj, "");
00180 }
00181 return obj.get();
00182 }
00183 }
00184
00185
00186 bool TheoryArithOld::kidsCanonical(const Expr& e) {
00187 if(isLeaf(e)) return true;
00188 bool res(true);
00189 for(int i=0; res && i<e.arity(); ++i) {
00190 Expr simp(canon(e[i]).getRHS());
00191 res = (e[i] == simp);
00192 IF_DEBUG(if(!res) debugger.getOS() << "\ne[" << i << "] = " << e[i]
00193 << "\nsimplified = " << simp << endl;)
00194 }
00195 return res;
00196 }
00197
00198
00199
00200
00201
00202
00203
00204
00205
00206
00207
00208
00209
00210
00211
00212
00213
00214
00215
00216
00217
00218 Theorem TheoryArithOld::canon(const Expr& e)
00219 {
00220 TRACE("arith canon","canon(",e,") {");
00221 DebugAssert(kidsCanonical(e), "TheoryArithOld::canon("+e.toString()+")");
00222 Theorem result;
00223 switch (e.getKind()) {
00224 case UMINUS: {
00225 Theorem thm = d_rules->uMinusToMult(e[0]);
00226 Expr e2 = thm.getRHS();
00227 result = transitivityRule(thm, canon(e2));
00228 }
00229 break;
00230 case PLUS:
00231
00232
00233
00234
00235
00236
00237 result = d_rules->canonPlus(e);
00238 break;
00239 case MINUS: {
00240 DebugAssert(e.arity() == 2,"");
00241 Theorem minus_eq_sum = d_rules->minusToPlus(e[0], e[1]);
00242
00243 Expr sum(minus_eq_sum.getRHS());
00244 Theorem thm(canon(sum[1]));
00245 if(thm.getLHS() == thm.getRHS())
00246 result = canonThm(minus_eq_sum);
00247
00248 else {
00249 vector<unsigned> changed;
00250 vector<Theorem> thms;
00251 changed.push_back(1);
00252 thms.push_back(thm);
00253 Theorem sum_eq_canon = canonThm(substitutivityRule(sum, changed, thms));
00254 result = transitivityRule(minus_eq_sum, sum_eq_canon);
00255 }
00256 break;
00257 }
00258
00259 case MULT:
00260 result = d_rules->canonMult(e);
00261 break;
00262
00263
00264
00265
00266
00267
00268
00269
00270
00271
00272
00273
00274
00275
00276
00277
00278
00279
00280
00281
00282
00283
00284
00285
00286
00287
00288
00289
00290
00291
00292
00293
00294
00295
00296
00297
00298
00299
00300
00301
00302
00303
00304
00305
00306
00307
00308
00309
00310
00311
00312
00313
00314
00315
00316
00317
00318
00319
00320
00321
00322
00323 case DIVIDE:{
00324
00325
00326
00327
00328
00329
00330
00331
00332
00333
00334
00335
00336
00337
00338
00339
00340
00341
00342
00343
00344
00345 if (e[1].getKind() == PLUS)
00346 throw ArithException("Divide by a PLUS expression not handled in"+e.toString());
00347 result = d_rules->canonDivide(e);
00348 break;
00349 }
00350 case POW:
00351 if(e[1].isRational())
00352 result = d_rules->canonPowConst(e);
00353 else {
00354
00355 if (e[0].isRational() && e[0].getRational() == 1) {
00356 result = d_rules->powerOfOne(e);
00357 } else
00358 result = reflexivityRule(e);
00359 }
00360 break;
00361 default:
00362 result = reflexivityRule(e);
00363 break;
00364 }
00365 TRACE("arith canon","canon => ",result," }");
00366 return result;
00367 }
00368
00369
00370 Theorem
00371 TheoryArithOld::canonSimplify(const Expr& e) {
00372 TRACE("arith simplify", "canonSimplify(", e, ") {");
00373 DebugAssert(kidsCanonical(e),
00374 "TheoryArithOld::canonSimplify("+e.toString()+")");
00375 DebugAssert(leavesAreSimp(e), "Expected leaves to be simplified");
00376 Expr tmp(e);
00377 Theorem thm = canon(e);
00378 if(thm.getRHS().hasFind())
00379 thm = transitivityRule(thm, find(thm.getRHS()));
00380
00381 DebugAssert(thm.getRHS() == simplifyExpr(thm.getRHS()),
00382 "canonSimplify("+e.toString()+")\n"
00383 +"canon(e) = "+thm.getRHS().toString()
00384 +"\nsimplify(canon(e)) = "+simplifyExpr(thm.getRHS()).toString());
00385
00386
00387
00388
00389
00390
00391
00392
00393 TRACE("arith", "canonSimplify =>", thm, " }");
00394 return thm;
00395 }
00396
00397
00398
00399
00400 Theorem
00401 TheoryArithOld::canonPred(const Theorem& thm) {
00402 vector<Theorem> thms;
00403 DebugAssert(thm.getExpr().arity() == 2,
00404 "TheoryArithOld::canonPred: bad theorem: "+thm.toString());
00405 Expr e(thm.getExpr());
00406 thms.push_back(canonSimplify(e[0]));
00407 thms.push_back(canonSimplify(e[1]));
00408 Theorem result = iffMP(thm, substitutivityRule(e.getOp(), thms));
00409
00410 return result;
00411 }
00412
00413
00414
00415
00416 Theorem
00417 TheoryArithOld::canonPredEquiv(const Theorem& thm) {
00418 vector<Theorem> thms;
00419 DebugAssert(thm.getRHS().arity() == 2,
00420 "TheoryArithOld::canonPredEquiv: bad theorem: "+thm.toString());
00421 Expr e(thm.getRHS());
00422 thms.push_back(canonSimplify(e[0]));
00423 thms.push_back(canonSimplify(e[1]));
00424 Theorem result = transitivityRule(thm, substitutivityRule(e.getOp(), thms));
00425
00426 return result;
00427 }
00428
00429
00430
00431
00432
00433 Theorem
00434 TheoryArithOld::canonConjunctionEquiv(const Theorem& thm) {
00435 vector<Theorem> thms;
00436 return thm;
00437 }
00438
00439
00440
00441
00442
00443
00444
00445
00446
00447 Theorem TheoryArithOld::doSolve(const Theorem& thm)
00448 {
00449 const Expr& e = thm.getExpr();
00450 if (e.isTrue() || e.isFalse()) return thm;
00451 TRACE("arith eq","doSolve(",e,") {");
00452 DebugAssert(thm.isRewrite(), "thm = "+thm.toString());
00453 Theorem eqnThm;
00454 vector<Theorem> thms;
00455
00456 if(e[0].isRational() && e[0].getRational() == 0)
00457 eqnThm = thm;
00458 else {
00459 eqnThm = iffMP(thm, d_rules->rightMinusLeft(e));
00460 eqnThm = canonPred(eqnThm);
00461 }
00462
00463
00464 Expr right = eqnThm.getRHS();
00465
00466 if (right.isRational()) {
00467 Theorem result = iffMP(eqnThm, d_rules->constPredicate(eqnThm.getExpr()));
00468 TRACE("arith eq","doSolve => ",result," }");
00469 return result;
00470 }
00471
00472
00473 eqnThm = iffMP(eqnThm, normalize(eqnThm.getExpr()));
00474 TRACE("arith eq","doSolve => ",eqnThm.getExpr()," }");
00475 right = eqnThm.getRHS();
00476
00477
00478
00479
00480 try {
00481 if (isMult(right)) {
00482 DebugAssert(right.arity() > 1, "Expected arity > 1");
00483 if (right[0].isRational()) {
00484 Rational r = right[0].getRational();
00485 if (r == 0) return getCommonRules()->trueTheorem();
00486 else if (r == 1) {
00487 enqueueFact(iffMP(eqnThm, d_rules->multEqZero(eqnThm.getExpr())));
00488 return getCommonRules()->trueTheorem();
00489 }
00490 Theorem res = iffMP(eqnThm,
00491 d_rules->multEqn(eqnThm.getLHS(),
00492 right, rat(1/r)));
00493 res = canonPred(res);
00494 return doSolve(res);
00495 }
00496 else {
00497 enqueueFact(iffMP(eqnThm, d_rules->multEqZero(eqnThm.getExpr())));
00498 return getCommonRules()->trueTheorem();
00499 }
00500 }
00501 else if (isPow(right)) {
00502 DebugAssert(right.arity() == 2, "Expected arity 2");
00503 if (right[0].isRational()) {
00504 return doSolve(iffMP(eqnThm, d_rules->powEqZero(eqnThm.getExpr())));
00505 }
00506 throw ArithException("Can't solve exponential eqn: "+eqnThm.toString());
00507 }
00508 else {
00509 if(!isInteger(right)) {
00510 return processRealEq(eqnThm);
00511 }
00512 else {
00513 return processIntEq(eqnThm);
00514 }
00515 }
00516 } catch(ArithException& e) {
00517 FatalAssert(false, "We should never get here!!! : " + e.toString());
00518
00519
00520
00521
00522
00523
00524
00525
00526
00527
00528
00529
00530
00531
00532
00533
00534
00535
00536
00537
00538
00539
00540
00541
00542
00543
00544
00545
00546
00547
00548
00549
00550
00551
00552
00553
00554 }
00555 FatalAssert(false, "");
00556 return Theorem();
00557 }
00558
00559
00560
00561
00562
00563 bool TheoryArithOld::pickIntEqMonomial(const Expr& right, Expr& isolated, bool& nonlin)
00564 {
00565 DebugAssert(isPlus(right) && right.arity() > 1,
00566 "TheoryArithOld::pickIntEqMonomial right is wrong :-): " +
00567 right.toString());
00568 DebugAssert(right[0].isRational(),
00569 "TheoryArithOld::pickIntEqMonomial. right[0] must be const" +
00570 right.toString());
00571
00572
00573
00574
00575
00576 Expr::iterator istart = right.begin(), iend = right.end();
00577 istart++;
00578 Expr::iterator i = istart, j;
00579 bool found = false;
00580 nonlin = false;
00581 Rational min, coeff;
00582 Expr leaf;
00583 for(; i != iend; ++i) {
00584 if (isLeaf(*i)) {
00585 leaf = *i;
00586 coeff = 1;
00587 }
00588 else if (isMult(*i) && (*i).arity() == 2 && (*i)[0].isRational() && isLeaf((*i)[1])) {
00589 leaf = (*i)[1];
00590 coeff = abs((*i)[0].getRational());
00591 }
00592 else {
00593 nonlin = true;
00594 continue;
00595 }
00596 for (j = istart; j != iend; ++j) {
00597 if (j != i && isLeafIn(leaf, *j)) break;
00598 }
00599 if (j == iend) {
00600 if (!found || min > coeff) {
00601 min = coeff;
00602 isolated = *i;
00603 found = true;
00604 }
00605 }
00606 }
00607 return found;
00608 }
00609
00610
00611
00612
00613
00614 Theorem
00615 TheoryArithOld::processRealEq(const Theorem& eqn)
00616 {
00617 DebugAssert(eqn.getLHS().isRational() &&
00618 eqn.getLHS().getRational() == 0,
00619 "processRealEq invariant violated");
00620 Expr right = eqn.getRHS();
00621
00622
00623
00624
00625
00626
00627
00628
00629
00630 bool found = false;
00631 Expr left;
00632
00633 if (isPlus(right)) {
00634 DebugAssert(right[0].isRational(), "Expected first term to be rational");
00635 for(int i = 1, iend = right.arity(); i < iend; ++i) {
00636 Expr c = right[i];
00637 DebugAssert(!isRational(c), "Expected non-rational");
00638 if(!isInteger(c)) {
00639 if (isLeaf(c) ||
00640 ((isMult(c) && c.arity() == 2 && isLeaf(c[1])))) {
00641 Expr leaf = isLeaf(c) ? c : c[1];
00642 int j;
00643 for (j = 1; j < iend; ++j) {
00644 if (j!= i
00645 && isLeafIn(leaf, right[j])
00646 ) {
00647 break;
00648 }
00649 }
00650 if (j == iend) {
00651 left = c;
00652 found = true;
00653 break;
00654 }
00655 }
00656 }
00657 }
00658 }
00659 else if ((isMult(right) && right.arity() == 2 && isLeaf(right[1])) ||
00660 isLeaf(right)) {
00661 left = right;
00662 found = true;
00663 }
00664
00665 if (!found) {
00666
00667
00668
00669
00670
00671
00672
00673 if (isNonlinearEq(eqn.getExpr()))
00674 return processIntEq(eqn);
00675 else throw
00676 ArithException("Can't find a leaf for solve in "+eqn.toString());
00677 }
00678
00679 Rational r = -1;
00680 if (isMult(left)) {
00681 DebugAssert(left.arity() == 2, "only leaf should be chosen as lhs");
00682 DebugAssert(left[0].getRational() != 0, "left = "+left.toString());
00683 r = -1/left[0].getRational();
00684 left = left[1];
00685 }
00686
00687 DebugAssert(isReal(getBaseType(left)) && !isInteger(left),
00688 "TheoryArithOld::ProcessRealEq: left is integer:\n left = "
00689 +left.toString());
00690
00691
00692 Theorem result(iffMP(eqn,
00693 d_rules->multEqn(eqn.getLHS(), eqn.getRHS(), rat(r))));
00694 result = canonPred(result);
00695
00696
00697 result = iffMP(result, d_rules->plusPredicate(result.getLHS(),
00698 result.getRHS(), left, EQ));
00699 result = canonPred(result);
00700 TRACE("arith","processRealEq => ",result," }");
00701 return result;
00702 }
00703
00704
00705 void TheoryArithOld::getFactors(const Expr& e, set<Expr>& factors)
00706 {
00707 switch (e.getKind()) {
00708 case RATIONAL_EXPR: break;
00709 case MULT: {
00710 Expr::iterator i = e.begin(), iend = e.end();
00711 for (; i != iend; ++i) {
00712 getFactors(*i, factors);
00713 }
00714 break;
00715 }
00716 case POW: {
00717 DebugAssert(e.arity() == 2, "invariant violated");
00718 if (!isIntegerConst(e[0]) || e[0].getRational() <= 0) {
00719 throw ArithException("not positive integer exponent in "+e.toString());
00720 }
00721 if (isLeaf(e[1])) factors.insert(e[1]);
00722 break;
00723 }
00724 default: {
00725 DebugAssert(isLeaf(e), "expected leaf");
00726 DebugAssert(factors.find(e) == factors.end(), "expected new entry");
00727 factors.insert(e);
00728 break;
00729 }
00730 }
00731 }
00732
00733
00734
00735
00736
00737
00738 Theorem
00739 TheoryArithOld::processSimpleIntEq(const Theorem& eqn)
00740 {
00741 TRACE("arith eq", "processSimpleIntEq(", eqn.getExpr(), ") {");
00742 DebugAssert(eqn.isRewrite(),
00743 "TheoryArithOld::processSimpleIntEq: eqn must be equality" +
00744 eqn.getExpr().toString());
00745
00746 Expr right = eqn.getRHS();
00747
00748 DebugAssert(eqn.getLHS().isRational() && 0 == eqn.getLHS().getRational(),
00749 "TheoryArithOld::processSimpleIntEq: LHS must be 0:\n" +
00750 eqn.getExpr().toString());
00751
00752 DebugAssert(!isMult(right) && !isPow(right), "should have been handled above");
00753 if (isPlus(right)) {
00754 if (2 == right.arity() &&
00755 (isLeaf(right[1]) ||
00756 (isMult(right[1]) && right[1].arity() == 2 && right[1][0].isRational() && isLeaf(right[1][1])))) {
00757
00758 Expr c,x;
00759 separateMonomial(right[1], c, x);
00760 Theorem isIntx(isIntegerThm(x));
00761 DebugAssert(!isIntx.isNull(), "right = "+right.toString()
00762 +"\n x = "+x.toString());
00763 Theorem res(iffMP(eqn, d_rules->intVarEqnConst(eqn.getExpr(), isIntx)));
00764 TRACE("arith eq", "processSimpleIntEq[0 = c + a*x] => ", res, " }");
00765 return res;
00766 }
00767
00768 Expr isolated;
00769 bool nonlin;
00770 if (pickIntEqMonomial(right, isolated, nonlin)) {
00771 TRACE("arith eq", "processSimpleIntEq: isolated = ", isolated, "");
00772
00773
00774
00775
00776
00777 Rational r = isMult(isolated) ?
00778 ((isolated[0].getRational() > 0) ? -1 : 1) : -1;
00779 Theorem result;
00780 if (-1 == r) {
00781
00782
00783 result = iffMP(eqn, d_rules->multEqn(eqn.getLHS(), right, rat(r)));
00784 result = canonPred(result);
00785 Expr e = result.getRHS();
00786
00787
00788 result = iffMP(result,
00789 d_rules->plusPredicate(result.getLHS(),result.getRHS(),
00790 isolated, EQ));
00791 } else {
00792
00793 const Rational& minusa = isolated[0].getRational();
00794 Rational a = -1*minusa;
00795 isolated = (a == 1)? isolated[1] : rat(a) * isolated[1];
00796
00797
00798 result = iffMP(eqn, d_rules->plusPredicate(eqn.getLHS(),
00799 right,isolated,EQ));
00800 }
00801
00802 result = canonPred(result);
00803
00804
00805 if(!isMult(isolated) || isolated[0].getRational() == 1) {
00806 TRACE("arith eq", "processSimpleIntEq[x = rhs] => ", result, " }");
00807 return result;
00808 } else if (!nonlin) {
00809 DebugAssert(isMult(isolated) && isolated[0].getRational() >= 2,
00810 "TheoryArithOld::processSimpleIntEq: isolated must be mult "
00811 "with coeff >= 2.\n isolated = " + isolated.toString());
00812
00813
00814 Expr lhs = result.getLHS();
00815 Expr rhs = result.getRHS();
00816 Expr a, x;
00817 separateMonomial(lhs, a, x);
00818 Theorem isIntLHS = isIntegerThm(x);
00819 vector<Theorem> isIntRHS;
00820 if(!isPlus(rhs)) {
00821 Expr c, v;
00822 separateMonomial(rhs, c, v);
00823 isIntRHS.push_back(isIntegerThm(v));
00824 DebugAssert(!isIntRHS.back().isNull(), "");
00825 } else {
00826 DebugAssert(isPlus(rhs), "rhs = "+rhs.toString());
00827 DebugAssert(rhs.arity() >= 2, "rhs = "+rhs.toString());
00828 Expr::iterator i=rhs.begin(), iend=rhs.end();
00829 ++i;
00830 for(; i!=iend; ++i) {
00831 Expr c, v;
00832 separateMonomial(*i, c, v);
00833 isIntRHS.push_back(isIntegerThm(v));
00834 DebugAssert(!isIntRHS.back().isNull(), "");
00835 }
00836 }
00837
00838 result = d_rules->eqElimIntRule(result, isIntLHS, isIntRHS);
00839
00840 result = getCommonRules()->skolemize(result);
00841
00842 DebugAssert(result.getExpr().isAnd() && result.getExpr().arity() == 2,
00843 "processSimpleIntEq: result = "+result.getExpr().toString());
00844 Theorem thm1 = canonPred(getCommonRules()->andElim(result, 0));
00845 Theorem thm2 = canonPred(getCommonRules()->andElim(result, 1));
00846 Theorem newRes = getCommonRules()->andIntro(thm1, thm2);
00847 if(newRes.getExpr() != result.getExpr()) result = newRes;
00848
00849 TRACE("arith eq", "processSimpleIntEq => ", result, " }");
00850 return result;
00851 }
00852 }
00853 throw
00854 ArithException("Can't find a leaf for solve in "+eqn.toString());
00855 } else {
00856
00857 Theorem result = symmetryRule(eqn);
00858 TRACE("arith eq", "processSimpleIntEq[x = 0] => ", result, " }");
00859 return result;
00860 }
00861 }
00862
00863
00864
00865
00866
00867
00868 Theorem
00869 TheoryArithOld::processIntEq(const Theorem& eqn)
00870 {
00871 TRACE("arith eq", "processIntEq(", eqn.getExpr(), ") {");
00872
00873 std::vector<Theorem> solvedAndNewEqs;
00874 Theorem newEq(eqn), result;
00875 bool done(false);
00876 do {
00877 result = processSimpleIntEq(newEq);
00878
00879 if(result.isRewrite()) {
00880 solvedAndNewEqs.push_back(result);
00881 done = true;
00882 }
00883 else if (result.getExpr().isBoolConst()) {
00884 done = true;
00885 }
00886 else {
00887 DebugAssert(result.getExpr().isAnd() && result.getExpr().arity() == 2,
00888 "TheoryArithOld::processIntEq("+eqn.getExpr().toString()
00889 +")\n result = "+result.getExpr().toString());
00890 solvedAndNewEqs.push_back(getCommonRules()->andElim(result, 0));
00891 newEq = getCommonRules()->andElim(result, 1);
00892 }
00893 } while(!done);
00894 Theorem res;
00895 if (result.getExpr().isFalse()) res = result;
00896 else if (solvedAndNewEqs.size() > 0)
00897 res = solvedForm(solvedAndNewEqs);
00898 else res = result;
00899 TRACE("arith eq", "processIntEq => ", res.getExpr(), " }");
00900 return res;
00901 }
00902
00903
00904
00905
00906
00907
00908
00909
00910
00911 Theorem
00912 TheoryArithOld::solvedForm(const vector<Theorem>& solvedEqs)
00913 {
00914 DebugAssert(solvedEqs.size() > 0, "TheoryArithOld::solvedForm()");
00915
00916
00917 TRACE_MSG("arith eq", "TheoryArithOld::solvedForm:solvedEqs(\n [");
00918 IF_DEBUG(if(debugger.trace("arith eq")) {
00919 for(vector<Theorem>::const_iterator j = solvedEqs.begin(),
00920 jend=solvedEqs.end(); j!=jend;++j)
00921 TRACE("arith eq", "", j->getExpr(), ",\n ");
00922 })
00923 TRACE_MSG("arith eq", " ]) {");
00924
00925
00926 vector<Theorem>::const_reverse_iterator
00927 i = solvedEqs.rbegin(),
00928 iend = solvedEqs.rend();
00929
00930
00931 ExprMap<Theorem> subst;
00932 for(; i!=iend; ++i) {
00933 if(i->isRewrite()) {
00934 Theorem thm = substAndCanonize(*i, subst);
00935 TRACE("arith eq", "solvedForm: subst["+i->getLHS().toString()+"] = ",
00936 thm.getExpr(), "");
00937 subst[i->getLHS()] = thm;
00938 }
00939 else {
00940
00941 DebugAssert(i->getExpr().isFalse(),
00942 "TheoryArithOld::solvedForm: an element of solvedEqs must "
00943 "be either EQ or FALSE: "+i->toString());
00944 return *i;
00945 }
00946 }
00947
00948
00949 vector<Theorem> thms;
00950 for(ExprMap<Theorem>::iterator i=subst.begin(), iend=subst.end();
00951 i!=iend; ++i)
00952 thms.push_back(i->second);
00953
00954 if (thms.size() > 1) return getCommonRules()->andIntro(thms);
00955 else return thms.back();
00956 }
00957
00958
00959
00960
00961
00962
00963
00964
00965 Theorem
00966 TheoryArithOld::substAndCanonize(const Expr& t, ExprMap<Theorem>& subst)
00967 {
00968 TRACE("arith eq", "substAndCanonize(", t, ") {");
00969
00970 if(subst.empty()) {
00971 Theorem res(reflexivityRule(t));
00972 TRACE("arith eq", "substAndCanonize[subst empty] => ", res, " }");
00973 return res;
00974 }
00975
00976 ExprMap<Theorem>::iterator i = subst.find(t), iend=subst.end();
00977 if(i!=iend) {
00978 TRACE("arith eq", "substAndCanonize[subst] => ", i->second, " }");
00979 return i->second;
00980 }
00981
00982 if(isLeaf(t)) {
00983 Theorem res(reflexivityRule(t));
00984 TRACE("arith eq", "substAndCanonize[i-leaf] => ", res, " }");
00985 return res;
00986 }
00987
00988 vector<Theorem> thms;
00989 vector<unsigned> changed;
00990 for(unsigned j=0, jend=t.arity(); j!=jend; ++j) {
00991 Theorem thm = substAndCanonize(t[j], subst);
00992 if(thm.getRHS() != t[j]) {
00993 thm = canonThm(thm);
00994 thms.push_back(thm);
00995 changed.push_back(j);
00996 }
00997 }
00998
00999 Theorem res;
01000 if(thms.size() > 0) {
01001 res = substitutivityRule(t, changed, thms);
01002 res = canonThm(res);
01003 }
01004 else
01005 res = reflexivityRule(t);
01006 TRACE("arith eq", "substAndCanonize => ", res, " }");
01007 return res;
01008 }
01009
01010
01011
01012
01013
01014
01015
01016 Theorem
01017 TheoryArithOld::substAndCanonize(const Theorem& eq, ExprMap<Theorem>& subst)
01018 {
01019
01020 if(subst.empty()) return eq;
01021
01022 DebugAssert(eq.isRewrite(), "TheoryArithOld::substAndCanonize: t = "
01023 +eq.getExpr().toString());
01024 const Expr& t = eq.getRHS();
01025
01026 Theorem thm = substAndCanonize(t, subst);
01027
01028 if(thm.getRHS() == t) return eq;
01029
01030 vector<Theorem> thms;
01031 vector<unsigned> changed;
01032 thms.push_back(thm);
01033 changed.push_back(1);
01034 return iffMP(eq, substitutivityRule(eq.getExpr(), changed, thms));
01035 }
01036
01037 void TheoryArithOld::processBuffer()
01038 {
01039
01040 bool varOnRHS;
01041
01042
01043 if (diffLogicOnly) return;
01044
01045 while (!inconsistent() && (d_bufferIdx_0 < d_buffer_0.size() || d_bufferIdx_1 < d_buffer_1.size() || d_bufferIdx_2 < d_buffer_2.size() || d_bufferIdx_3 < d_buffer_3.size())) {
01046
01047
01048 Theorem ineqThm;
01049 if (d_bufferIdx_0 < d_buffer_0.size()) {
01050 ineqThm = d_buffer_0[d_bufferIdx_0];
01051 d_bufferIdx_0 = d_bufferIdx_0 + 1;
01052 } else if (d_bufferIdx_1 < d_buffer_1.size()) {
01053 ineqThm = d_buffer_1[d_bufferIdx_1];
01054 d_bufferIdx_1 = d_bufferIdx_1 + 1;
01055 } else if (d_bufferIdx_2 < d_buffer_2.size()) {
01056 ineqThm = d_buffer_2[d_bufferIdx_2];
01057 d_bufferIdx_2 = d_bufferIdx_2 + 1;
01058 } else {
01059 ineqThm = d_buffer_3[d_bufferIdx_3];
01060 d_bufferIdx_3 = d_bufferIdx_3 + 1;
01061 }
01062
01063
01064
01065
01066
01067
01068
01069 const Expr& inequality = ineqThm.getExpr();
01070 Theorem inequalityFindThm = inequalityToFind(ineqThm, true);
01071 Expr inequalityFind = inequalityFindThm.getExpr();
01072
01073
01074
01075 TRACE("arith buffer", "processing: ", inequality, "");
01076 TRACE("arith buffer", "with find : ", inequalityFind, "");
01077
01078 if (!isIneq(inequalityFind)) {
01079 TRACE("arith buffer", "find not an inequality... ", "", "skipping");
01080 continue;
01081 }
01082
01083 if (alreadyProjected.find(inequalityFind) != alreadyProjected.end()) {
01084 TRACE("arith buffer", "already projected ... ", "", "skipping");
01085 continue;
01086 }
01087
01088
01089
01090
01091
01092 Expr dummy;
01093 alreadyProjected[inequality] = dummy;
01094 if (inequality != inequalityFind) {
01095
01096 alreadyProjected[inequalityFind] = dummy;
01097
01098 Expr rhs = inequalityFind[1];
01099
01100
01101 if(isPlus(rhs)) {
01102 for(Expr::iterator i=rhs.begin(), iend=rhs.end(); i!=iend; ++i) {
01103 Expr monomial = *i;
01104 updateStats(monomial);
01105 }
01106 } else
01107 updateStats(rhs);
01108 }
01109
01110
01111
01112 Rational c1, c2;
01113 Expr t1, t2;
01114
01115
01116 extractTermsFromInequality(inequalityFind, c1, t1, c2, t2);
01117 if (termLowerBound.find(t1) != termLowerBound.end() && c1 != termLowerBound[t1]) {
01118 TRACE("arith ineq", "skipping because stronger bounds asserted ", inequalityFind.toString(), ":" + t1.toString());
01119 DebugAssert(termLowerBoundThm.find(t1) != termLowerBoundThm.end(), "No lower bound on asserted atom!!! " + t1.toString());
01120 Theorem strongerBound = termLowerBoundThm[t1];
01121
01122 continue;
01123 }
01124
01125 Theorem thm1 = isolateVariable(inequalityFindThm, varOnRHS);
01126 const Expr& ineq = thm1.getExpr();
01127 if (ineq.isFalse())
01128 setInconsistent(thm1);
01129 else
01130 if(!ineq.isTrue()) {
01131
01132
01133 DebugAssert(varOnRHS? !isPlus(ineq[1]) : !isPlus(ineq[0]), "TheoryArithOld::processBuffer(): bad result from isolateVariable:\nineq = "+ineq.toString());
01134
01135 projectInequalities(thm1, varOnRHS);
01136 }
01137 }
01138 }
01139
01140
01141 void TheoryArithOld::updateStats(const Rational& c, const Expr& v)
01142 {
01143 TRACE("arith stats", "updateStats("+c.toString()+", ", v, ")");
01144
01145
01146 if (v.isRational()) return;
01147
01148 if (v.getType() != d_realType) {
01149
01150 if (c < 0) {
01151
01152 ExprMap<Rational>::iterator maxFind = maxCoefficientLeft.find(v);
01153 if (maxFind == maxCoefficientLeft.end()) {
01154 maxCoefficientLeft[v] = - c;
01155 TRACE("arith stats", "max left", "", "");
01156 }
01157 else
01158 if ((*maxFind).second < -c) {
01159 TRACE("arith stats", "max left", "", "");
01160 maxCoefficientLeft[v] = -c;
01161 }
01162 } else {
01163
01164 ExprMap<Rational>::iterator maxFind = maxCoefficientRight.find(v);
01165 if (maxFind == maxCoefficientRight.end()) {
01166 maxCoefficientRight[v] = c;
01167 TRACE("arith stats", "max right", "", "");
01168 }
01169 else
01170 if((*maxFind).second < c) {
01171 TRACE("arith stats", "max right", "", "");
01172 maxCoefficientRight[v] = c;
01173 }
01174 }
01175 }
01176
01177 if(c > 0) {
01178 if(d_countRight.count(v) > 0) d_countRight[v] = d_countRight[v] + 1;
01179 else d_countRight[v] = 1;
01180 }
01181 else
01182 if(d_countLeft.count(v) > 0) d_countLeft[v] = d_countLeft[v] + 1;
01183 else d_countLeft[v] = 1;
01184 }
01185
01186
01187 void TheoryArithOld::updateStats(const Expr& monomial)
01188 {
01189 Expr c, m;
01190 separateMonomial(monomial, c, m);
01191 updateStats(c.getRational(), m);
01192 }
01193
01194 int TheoryArithOld::extractTermsFromInequality(const Expr& inequality,
01195 Rational& c1, Expr& t1,
01196 Rational& c2, Expr& t2) {
01197
01198 TRACE("arith extract", "extract(", inequality.toString(), ")");
01199
01200 DebugAssert(isIneq(inequality), "extractTermsFromInequality: expexting an inequality got: " + inequality.getString() + ")");
01201
01202 Expr rhs = inequality[1];
01203
01204 c1 = 0;
01205
01206
01207 vector<Expr> positive_children, negative_children;
01208 if (isPlus(rhs)) {
01209 int start_i = 0;
01210 if (rhs[0].isRational()) {
01211 start_i = 1;
01212 c1 = -rhs[0].getRational();
01213 }
01214 int end_i = rhs.arity();
01215 for(int i = start_i; i < end_i; i ++) {
01216 const Expr& term = rhs[i];
01217 positive_children.push_back(term);
01218 negative_children.push_back(canon(multExpr(rat(-1),term)).getRHS());
01219 }
01220 } else {
01221 positive_children.push_back(rhs);
01222 negative_children.push_back(canon(multExpr(rat(-1), rhs)).getRHS());
01223 }
01224
01225 int num_vars = positive_children.size();
01226
01227
01228 t1 = (num_vars > 1 ? canon(plusExpr(positive_children)).getRHS() : positive_children[0]);
01229
01230
01231 c2 = -c1;
01232 t2 = (num_vars > 1 ? canon(plusExpr(negative_children)).getRHS() : negative_children[0]);
01233
01234 TRACE("arith extract", "extract: ", c1.toString() + " <= ", t1.toString());
01235
01236 return num_vars;
01237 }
01238
01239 bool TheoryArithOld::addToBuffer(const Theorem& thm, bool priority) {
01240
01241 TRACE("arith buffer", "addToBuffer(", thm.getExpr().toString(), ")");
01242
01243 Expr ineq = thm.getExpr();
01244 const Expr& rhs = thm.getExpr()[1];
01245
01246 bool nonLinear = false;
01247 Rational nonLinearConstant = 0;
01248 Expr compactNonLinear;
01249 Theorem compactNonLinearThm;
01250
01251
01252 if(isPlus(rhs)) {
01253 for(Expr::iterator i=rhs.begin(), iend=rhs.end(); i!=iend; ++i) {
01254 Expr monomial = *i;
01255 updateStats(monomial);
01256
01257 if (isMult(monomial)) {
01258 if ((monomial[0].isRational() && monomial.arity() >= 3) ||
01259 (!monomial[0].isRational() && monomial.arity() >= 2) ||
01260 (monomial.arity() == 2 && isPow(monomial[1])))
01261 nonLinear = true;
01262 }
01263 }
01264 if (nonLinear) {
01265 compactNonLinearThm = d_rules->compactNonLinearTerm(rhs);
01266 compactNonLinear = compactNonLinearThm.getRHS();
01267 }
01268 }
01269 else
01270 {
01271 updateStats(rhs);
01272 if (isMult(rhs))
01273 if ((rhs[0].isRational() && rhs.arity() >= 3)
01274 || (!rhs[0].isRational() && rhs.arity() >= 2)
01275 || (rhs.arity() == 2 && isPow(rhs[1]))) {
01276 nonLinear = true;
01277 compactNonLinear = rhs;
01278 compactNonLinearThm = reflexivityRule(compactNonLinear);
01279 }
01280 }
01281
01282 if (bufferedInequalities.find(ineq) != bufferedInequalities.end()) {
01283 TRACE("arith buffer", "addToBuffer()", "", "... already in db");
01284 if (formulaAtoms.find(ineq) != formulaAtoms.end()) {
01285 TRACE("arith buffer", "it's a formula atom, enqueuing.", "", "");
01286 enqueueFact(thm);
01287 }
01288 return false;
01289 }
01290
01291 if (nonLinear && (isMult(rhs) || compactNonLinear != rhs)) {
01292 TRACE("arith nonlinear", "compact version of ", rhs, " is " + compactNonLinear.toString());
01293
01294 Theorem thm1 = (compactNonLinear != rhs ?
01295 iffMP(thm, substitutivityRule(ineq, 1, compactNonLinearThm)) : thm);
01296
01297 Rational c = (isMult(rhs) ? 0 : compactNonLinear[0].getRational());
01298
01299 if (c <= 0) {
01300 thm1 = d_rules->nonLinearIneqSignSplit(thm1);
01301 TRACE("arith nonlinear", "spliting on signs : ", thm1.getExpr(), "");
01302 enqueueFact(thm1);
01303 }
01304 }
01305
01306
01307 Expr t1, t2;
01308 Rational c1, c2;
01309 int num_vars = extractTermsFromInequality(ineq, c1, t1, c2, t2);
01310
01311
01312 bool factIsDiffLogic = false;
01313 if (num_vars <= 2) {
01314
01315 TRACE("arith diff", t2, " < ", c2);
01316
01317
01318 Expr ax = (num_vars == 2 ? t2[1] : t2);
01319 Expr a_expr, x;
01320 separateMonomial(ax, a_expr, x);
01321 Rational a = a_expr.getRational();
01322 Expr by = (num_vars == 2 ? t2[2] : (a < 0 ? zero : rat(-1)*zero));
01323 Expr b_expr, y;
01324 separateMonomial(by, b_expr, y);
01325 Rational b = b_expr.getRational();
01326
01327
01328 if (!isLeaf(x) || !isLeaf(y))
01329 setIncomplete("Non-linear arithmetic inequalities");
01330
01331 if (a == 1 && b == -1) {
01332 diffLogicGraph.addEdge(x, y, c2, thm);
01333 factIsDiffLogic = true;
01334 }
01335 else if (a == -1 && b == 1) {
01336 diffLogicGraph.addEdge(y, x, c2, thm);
01337 factIsDiffLogic = true;
01338 }
01339
01340 else {
01341 diffLogicOnly = false;
01342 TRACE("arith diff", "not diff logic", thm.getExpr().toString(), "");
01343 }
01344
01345 if (diffLogicGraph.isUnsat()) {
01346 TRACE("diff unsat", "UNSAT", " : ", diffLogicGraph.getUnsatTheorem());
01347 setInconsistent(diffLogicGraph.getUnsatTheorem());
01348 return false;
01349 }
01350 } else {
01351 diffLogicOnly = false;
01352 TRACE("arith diff", "not diff logic", thm.getExpr().toString(), "");
01353 }
01354
01355
01356 CDMap<Expr, Rational>::iterator find_lower = termLowerBound.find(t1);
01357 if (find_lower != termLowerBound.end()) {
01358
01359 Rational found_c = (*find_lower).second;
01360
01361 if (c1 <= found_c && !(found_c == c1 && ineq.getKind() == LT)) {
01362 TRACE("arith buffer", "addToBuffer()", "", "... lower_bound subsumed");
01363
01364
01365
01366 return false;
01367 } else {
01368 Theorem oldLowerBound = termLowerBoundThm[t1];
01369 Expr oldIneq = oldLowerBound.getExpr();
01370 if (formulaAtoms.find(oldIneq) != formulaAtoms.end())
01371 enqueueFact(getCommonRules()->implMP(thm, d_rules->implyWeakerInequality(ineq, oldIneq)));
01372 termLowerBound[t1] = c1;
01373 termLowerBoundThm[t1] = thm;
01374 }
01375 } else {
01376 termLowerBound[t1] = c1;
01377 termLowerBoundThm[t1] = thm;
01378 }
01379
01380 CDMap<Expr, Rational>::iterator find_upper = termUpperBound.find(t2);
01381 if (find_upper != termUpperBound.end()) {
01382
01383 Rational found_c = (*find_upper).second;
01384
01385 if (found_c <= c2 && !(found_c == c2 && ineq.getKind() == LT)) {
01386 TRACE("arith buffer", "addToBuffer()", "", "... upper_bound subsumed");
01387
01388 return false;
01389 } else {
01390 termUpperBound[t2] = c2;
01391 termUpperBoundThm[t2] = thm;
01392 }
01393 } else {
01394 termUpperBound[t2] = c2;
01395 termUpperBoundThm[t2] = thm;
01396 }
01397
01398
01399 if (termUpperBound.find(t1) != termUpperBound.end() &&
01400 termLowerBound.find(t1) != termLowerBound.end() &&
01401 termUpperBound[t1] <= termLowerBound[t1]) {
01402 Theorem thm1 = termUpperBoundThm[t1];
01403 Theorem thm2 = termLowerBoundThm[t1];
01404 TRACE("arith propagate", "adding inequalities: ", thm1.getExpr().toString(), " with " + thm2.getExpr().toString());
01405 enqueueFact(d_rules->addInequalities(thm1, thm2));
01406 } else
01407 if (termUpperBound.find(t2) != termUpperBound.end() &&
01408 termLowerBound.find(t2) != termLowerBound.end() &&
01409 termUpperBound[t2] <= termLowerBound[t2]) {
01410 Theorem thm1 = termUpperBoundThm[t2];
01411 Theorem thm2 = termLowerBoundThm[t2];
01412 TRACE("arith propagate", "adding inequalities: ", thm1.getExpr().toString(), " with " + thm2.getExpr().toString());
01413 enqueueFact(d_rules->addInequalities(thm1, thm2));
01414 }
01415
01416 if (true) {
01417
01418
01419 AtomsMap::iterator find = formulaAtomLowerBound.find(t1);
01420 AtomsMap::iterator find_end = formulaAtomLowerBound.end();
01421 if (find != find_end) {
01422 set< pair<Rational, Expr> >::iterator bounds = (*find).second.begin();
01423 set< pair<Rational, Expr> >::iterator bounds_end = (*find).second.end();
01424 while (bounds != bounds_end) {
01425 TRACE("arith atoms", "trying propagation", ineq, (*bounds).second);
01426 const Expr& implied = (*bounds).second;
01427
01428 if ((*bounds).first < c1 || (!(ineq.getKind() == LE && implied.getKind() == LT) && (*bounds).first == c1)) {
01429
01430
01431
01432 Theorem impliedThm = getCommonRules()->implMP(thm, d_rules->implyWeakerInequality(ineq, implied));
01433 enqueueFact(impliedThm);
01434 }
01435 bounds ++;
01436 }
01437 }
01438
01439
01440
01441
01442
01443 find = formulaAtomUpperBound.find(t1);
01444 find_end = formulaAtomUpperBound.end();
01445 if (find != find_end) {
01446 set< pair<Rational, Expr> >::iterator bounds = (*find).second.begin();
01447 set< pair<Rational, Expr> >::iterator bounds_end = (*find).second.end();
01448 while (bounds != bounds_end) {
01449 TRACE("arith atoms", "trying propagation", ineq, (*bounds).second);
01450 const Expr& implied = (*bounds).second;
01451
01452 if ((*bounds).first < c1) {
01453 Theorem impliedThm = getCommonRules()->implMP(thm, d_rules->implyNegatedInequality(ineq, implied));
01454 enqueueFact(impliedThm);
01455 }
01456 bounds ++;
01457 }
01458 }
01459 }
01460
01461
01462 theoryCore()->getResource();
01463
01464
01465 if (theoryCore()->outOfResources()) return false;
01466
01467
01468
01469 if (alreadyProjected.find(ineq) == alreadyProjected.end()) {
01470
01471 if (dontBuffer.find(ineq) == dontBuffer.end()) {
01472
01473 if (priority)
01474 d_buffer_0.push_back(thm);
01475 else {
01476
01477 if (num_vars == 1) d_buffer_1.push_back(thm);
01478 else if (num_vars == 2) d_buffer_2.push_back(thm);
01479 else d_buffer_3.push_back(thm);
01480 }
01481
01482 if (factIsDiffLogic) diff_logic_size = diff_logic_size + 1;
01483 }
01484 }
01485
01486
01487 bufferedInequalities[ineq] = thm;
01488
01489
01490 if (!ineq.hasFind())
01491 theoryCore()->setupTerm(ineq, this, thm);
01492
01493 return true;
01494 }
01495
01496
01497 Theorem TheoryArithOld::isolateVariable(const Theorem& inputThm,
01498 bool& isolatedVarOnRHS)
01499 {
01500 Theorem result(inputThm);
01501 const Expr& e = inputThm.getExpr();
01502 TRACE("arith","isolateVariable(",e,") {");
01503 TRACE("arith ineq", "isolateVariable(", e, ") {");
01504
01505 DebugAssert(isLT(e)||isLE(e),
01506 "TheoryArithOld::isolateVariable: " + e.toString() +
01507 " wrong kind");
01508 int kind = e.getKind();
01509 DebugAssert(e[0].isRational() && e[0].getRational() == 0,
01510 "TheoryArithOld::isolateVariable: theorem must be of "
01511 "the form 0 < rhs: " + inputThm.toString());
01512
01513 const Expr& zero = e[0];
01514 Expr right = e[1];
01515
01516 if (right.isRational()) {
01517 result = iffMP(result, d_rules->constPredicate(e));
01518 TRACE("arith ineq","isolateVariable => ",result.getExpr()," }");
01519 TRACE("arith","isolateVariable => ",result," }");
01520 return result;
01521 }
01522
01523
01524
01525
01526 Expr factor(computeNormalFactor(right, false));
01527 TRACE("arith", "isolateVariable: factor = ", factor, "");
01528 DebugAssert(factor.getRational() > 0,
01529 "isolateVariable: factor="+factor.toString());
01530
01531 if(factor.getRational() != 1) {
01532 result = iffMP(result, d_rules->multIneqn(e, factor));
01533
01534 result = canonPred(result);
01535 result = rafineInequalityToInteger(result);
01536 right = result.getExpr()[1];
01537 }
01538
01539
01540 Expr isolatedMonomial = right;
01541
01542 if (isPlus(right))
01543 isolatedMonomial = pickMonomial(right);
01544
01545 TRACE("arith ineq", "isolatedMonomial => ",isolatedMonomial,"");
01546
01547
01548
01549
01550 alreadyProjected[e] = isolatedMonomial;
01551
01552 Rational r = -1;
01553 isolatedVarOnRHS = true;
01554 if (isMult(isolatedMonomial)) {
01555 r = ((isolatedMonomial[0].getRational()) >= 0)? -1 : 1;
01556 isolatedVarOnRHS =
01557 ((isolatedMonomial[0].getRational()) >= 0)? true : false;
01558 }
01559 isolatedMonomial = canon(rat(-1)*isolatedMonomial).getRHS();
01560 TRACE("arith ineq", "-(isolatedMonomial) => ",isolatedMonomial,"");
01561
01562 result = iffMP(result, d_rules->plusPredicate(zero, right,
01563 isolatedMonomial, kind));
01564
01565 TRACE("arith ineq", "resutl => ",result,"");
01566 result = canonPred(result);
01567 if(1 != r) {
01568 result = iffMP(result, d_rules->multIneqn(result.getExpr(), rat(r)));
01569 result = canonPred(result);
01570 }
01571 TRACE("arith ineq","isolateVariable => ",result.getExpr()," }");
01572 TRACE("arith","isolateVariable => ",result," }");
01573 return result;
01574 }
01575
01576 Expr
01577 TheoryArithOld::computeNormalFactor(const Expr& right, bool normalizeConstants) {
01578
01579
01580 Rational factor;
01581 if(isPlus(right)) {
01582 vector<Rational> nums, denoms;
01583 for(int i=0, iend=right.arity(); i<iend; ++i) {
01584 switch(right[i].getKind()) {
01585 case RATIONAL_EXPR:
01586 if (normalizeConstants) {
01587 Rational c(abs(right[i].getRational()));
01588 nums.push_back(c.getNumerator());
01589 denoms.push_back(c.getDenominator());
01590 break;
01591 }
01592 break;
01593 case MULT: {
01594 Rational c(abs(right[i][0].getRational()));
01595 nums.push_back(c.getNumerator());
01596 denoms.push_back(c.getDenominator());
01597 break;
01598 }
01599 default:
01600 nums.push_back(1);
01601 denoms.push_back(1);
01602 break;
01603 }
01604 }
01605 Rational gcd_nums = gcd(nums);
01606
01607
01608
01609
01610 factor = (gcd_nums==0)? 0 : (lcm(denoms) / gcd_nums);
01611 } else if(isMult(right)) {
01612 const Rational& r = right[0].getRational();
01613 factor = (r==0)? 0 : (1/abs(r));
01614 }
01615 else
01616 factor = 1;
01617 return rat(factor);
01618 }
01619
01620
01621 bool TheoryArithOld::lessThanVar(const Expr& isolatedMonomial, const Expr& var2)
01622 {
01623 DebugAssert(!isRational(var2) && !isRational(isolatedMonomial),
01624 "TheoryArithOld::findMaxVar: isolatedMonomial cannot be rational" +
01625 isolatedMonomial.toString());
01626 Expr c, var0, var1;
01627 separateMonomial(isolatedMonomial, c, var0);
01628 separateMonomial(var2, c, var1);
01629 return var0 < var1;
01630 }
01631
01632
01633
01634
01635
01636
01637 bool TheoryArithOld::isStale(const Expr& e) {
01638 if(e.isTerm())
01639 return e != find(e).getRHS();
01640
01641
01642 bool stale=false;
01643 for(Expr::iterator i=e.begin(), iend=e.end(); !stale && i!=iend; ++i)
01644 stale = isStale(*i);
01645 return stale;
01646 }
01647
01648
01649 bool TheoryArithOld::isStale(const TheoryArithOld::Ineq& ineq) {
01650 TRACE("arith stale", "isStale(", ineq, ") {");
01651 const Expr& ineqExpr = ineq.ineq().getExpr();
01652 const Rational& c = freeConstIneq(ineqExpr, ineq.varOnRHS());
01653 bool strict(isLT(ineqExpr));
01654 const FreeConst& fc = ineq.getConst();
01655
01656 bool subsumed;
01657
01658 if (ineqExpr.hasFind() && find(ineqExpr[1]).getRHS() != ineqExpr[1])
01659 return true;
01660
01661 if(ineq.varOnRHS()) {
01662 subsumed = (c < fc.getConst() ||
01663 (c == fc.getConst() && !strict && fc.strict()));
01664 } else {
01665 subsumed = (c > fc.getConst() ||
01666 (c == fc.getConst() && strict && !fc.strict()));
01667 }
01668
01669 bool res;
01670 if(subsumed) {
01671 res = true;
01672 TRACE("arith ineq", "isStale[subsumed] => ", res? "true" : "false", " }");
01673 }
01674 else {
01675 res = isStale(ineqExpr);
01676 TRACE("arith ineq", "isStale[updated] => ", res? "true" : "false", " }");
01677 }
01678 return res;
01679 }
01680
01681
01682 void TheoryArithOld::separateMonomial(const Expr& e, Expr& c, Expr& var) {
01683 TRACE("separateMonomial", "separateMonomial(", e, ")");
01684 DebugAssert(!isPlus(e),
01685 "TheoryArithOld::separateMonomial(e = "+e.toString()+")");
01686 if(isMult(e)) {
01687 DebugAssert(e.arity() >= 2,
01688 "TheoryArithOld::separateMonomial(e = "+e.toString()+")");
01689 c = e[0];
01690 if(e.arity() == 2) var = e[1];
01691 else {
01692 vector<Expr> kids = e.getKids();
01693 kids[0] = rat(1);
01694 var = multExpr(kids);
01695 }
01696 } else {
01697 c = rat(1);
01698 var = e;
01699 }
01700 DebugAssert(c.isRational(), "TheoryArithOld::separateMonomial(e = "
01701 +e.toString()+", c = "+c.toString()+")");
01702 DebugAssert(!isMult(var) || (var[0].isRational() && var[0].getRational()==1),
01703 "TheoryArithOld::separateMonomial(e = "
01704 +e.toString()+", var = "+var.toString()+")");
01705 }
01706
01707
01708 void TheoryArithOld::projectInequalities(const Theorem& theInequality,
01709 bool isolatedVarOnRHS)
01710 {
01711
01712 TRACE("arith project", "projectInequalities(", theInequality.getExpr(),
01713 ", isolatedVarOnRHS="+string(isolatedVarOnRHS? "true" : "false")
01714 +") {");
01715 DebugAssert(isLE(theInequality.getExpr()) ||
01716 isLT(theInequality.getExpr()),
01717 "TheoryArithOld::projectIsolatedVar: "\
01718 "theInequality is of the wrong form: " +
01719 theInequality.toString());
01720
01721
01722
01723 Theorem theIneqThm(theInequality);
01724 Expr theIneq = theIneqThm.getExpr();
01725
01726
01727 if(isLT(theIneq)) {
01728 Theorem isIntLHS(isIntegerThm(theIneq[0]));
01729 Theorem isIntRHS(isIntegerThm(theIneq[1]));
01730 if ((!isIntLHS.isNull() && !isIntRHS.isNull())) {
01731 Theorem thm = d_rules->lessThanToLE(theInequality, isIntLHS, isIntRHS, !isolatedVarOnRHS);
01732 theIneqThm = canonPred(iffMP(theIneqThm, thm));
01733 theIneq = theIneqThm.getExpr();
01734 }
01735 }
01736
01737 Expr isolatedMonomial = isolatedVarOnRHS ? theIneq[1] : theIneq[0];
01738
01739 Expr monomialVar, a;
01740 separateMonomial(isolatedMonomial, a, monomialVar);
01741
01742 bool subsumed;
01743 const FreeConst& bestConst = updateSubsumptionDB(theIneq, isolatedVarOnRHS, subsumed);
01744
01745 if(subsumed) {
01746 IF_DEBUG(debugger.counter("subsumed inequalities")++;)
01747 TRACE("arith ineq", "subsumed inequality: ", theIneq, "");
01748 } else {
01749
01750
01751 if(isMult(monomialVar) || isPow(monomialVar))
01752 setIncomplete("Non-linear arithmetic inequalities");
01753
01754
01755
01756
01757
01758 theoryCore()->setupTerm(theIneq[0], this, theIneqThm);
01759 theoryCore()->setupTerm(theIneq[1], this, theIneqThm);
01760
01761 ExprMap<CDList<Ineq> *>& db1 = isolatedVarOnRHS ? d_inequalitiesRightDB : d_inequalitiesLeftDB;
01762 ExprMap<CDList<Ineq> *>::iterator it1 = db1.find(monomialVar);
01763 if(it1 == db1.end()) {
01764 CDList<Ineq> * list = new(true) CDList<Ineq>(theoryCore()->getCM()->getCurrentContext());
01765 list->push_back(Ineq(theIneqThm, isolatedVarOnRHS, bestConst));
01766 db1[monomialVar] = list;
01767 }
01768 else
01769 ((*it1).second)->push_back(Ineq(theIneqThm, isolatedVarOnRHS, bestConst));
01770
01771 ExprMap<CDList<Ineq> *>& db2 = isolatedVarOnRHS ? d_inequalitiesLeftDB : d_inequalitiesRightDB;
01772 ExprMap<CDList<Ineq> *>::iterator it = db2.find(monomialVar);
01773 if(it == db2.end()) {
01774 TRACE_MSG("arith ineq", "projectInequalities[not in DB] => }");
01775 return;
01776 }
01777
01778 CDList<Ineq>& listOfDBIneqs = *((*it).second);
01779 Theorem betaLTt, tLTalpha, thm;
01780 for(int i = listOfDBIneqs.size() - 1; !inconsistent() && i >= 0; --i) {
01781 const Ineq& ineqEntry = listOfDBIneqs[i];
01782 const Theorem& ineqThm = ineqEntry.ineq();
01783
01784
01785
01786 if(!isStale(ineqEntry)) {
01787 betaLTt = isolatedVarOnRHS ? theIneqThm : ineqThm;
01788 tLTalpha = isolatedVarOnRHS ? ineqThm : theIneqThm;
01789
01790 thm = normalizeProjectIneqs(betaLTt, tLTalpha);
01791 if (thm.isNull()) continue;
01792
01793 IF_DEBUG(debugger.counter("real shadows")++;)
01794
01795
01796 Expr e(thm.getExpr());
01797
01798 if(e.isFalse()) {
01799 setInconsistent(thm);
01800 TRACE_MSG("arith ineq", "projectInequalities[inconsistent] => }");
01801 return;
01802 }
01803 else {
01804 if(!e.isTrue() && !e.isEq()) {
01805
01806 addToBuffer(thm, false);
01807 }
01808 else if(e.isEq())
01809 enqueueFact(thm);
01810 }
01811 } else {
01812 IF_DEBUG(debugger.counter("stale inequalities")++;)
01813 }
01814 }
01815 }
01816
01817 TRACE_MSG("arith ineq", "projectInequalities => }");
01818 }
01819
01820 Theorem TheoryArithOld::normalizeProjectIneqs(const Theorem& ineqThm1,
01821 const Theorem& ineqThm2)
01822 {
01823
01824
01825 Theorem betaLTt = ineqThm1, tLTalpha = ineqThm2;
01826 Expr ineq1 = betaLTt.getExpr();
01827 Expr ineq2 = tLTalpha.getExpr();
01828 Expr c,x;
01829 separateMonomial(ineq2[0], c, x);
01830 Theorem isIntx(isIntegerThm(x));
01831 Theorem isIntBeta(isIntegerThm(ineq1[0]));
01832 Theorem isIntAlpha(isIntegerThm(ineq2[1]));
01833 bool isInt = !(isIntx.isNull() || isIntBeta.isNull() || isIntAlpha.isNull());
01834
01835 TRACE("arith ineq", "normalizeProjectIneqs(", ineq1,
01836 ", "+ineq2.toString()+") {");
01837 DebugAssert((isLE(ineq1) || isLT(ineq1)) &&
01838 (isLE(ineq2) || isLT(ineq2)),
01839 "TheoryArithOld::normalizeProjectIneqs: Wrong Kind inputs: " +
01840 ineq1.toString() + ineq2.toString());
01841 DebugAssert(!isPlus(ineq1[1]) && !isPlus(ineq2[0]),
01842 "TheoryArithOld::normalizeProjectIneqs: Wrong Kind inputs: " +
01843 ineq1.toString() + ineq2.toString());
01844
01845
01846
01847 Rational factor1 = 1, factor2 = 1;
01848 Rational b = isMult(ineq1[1]) ? (ineq1[1])[0].getRational() : 1;
01849 Rational a = isMult(ineq2[0]) ? (ineq2[0])[0].getRational() : 1;
01850 if(b != a) {
01851 factor1 = a;
01852 factor2 = b;
01853 }
01854
01855
01856
01857
01858
01859
01860
01861 if(isInt && (a >= 2 || b >= 2)) {
01862 Theorem intResult;
01863 if(a <= b)
01864 intResult = d_rules->darkGrayShadow2ab(betaLTt, tLTalpha,
01865 isIntAlpha, isIntBeta, isIntx);
01866 else
01867 intResult = d_rules->darkGrayShadow2ba(betaLTt, tLTalpha,
01868 isIntAlpha, isIntBeta, isIntx);
01869 enqueueFact(intResult);
01870
01871 const Expr& DorG = intResult.getExpr();
01872 DebugAssert(DorG.isOr() && DorG.arity()==2, "DorG = "+DorG.toString());
01873 const Expr& G = DorG[1];
01874 DebugAssert(G.getKind()==GRAY_SHADOW, "G = "+G.toString());
01875
01876
01877
01878
01879
01880 Expr tmp = simplifyExpr(!G);
01881 if (!tmp.isBoolConst())
01882 addSplitter(tmp, 1);
01883 IF_DEBUG(debugger.counter("dark+gray shadows")++;)
01884
01885
01886
01887 }
01888
01889
01890 if(1 != factor1) {
01891 Theorem thm2 = iffMP(betaLTt, d_rules->multIneqn(ineq1, rat(factor1)));
01892 betaLTt = canonPred(thm2);
01893 ineq1 = betaLTt.getExpr();
01894 }
01895 if(1 != factor2) {
01896 Theorem thm2 = iffMP(tLTalpha, d_rules->multIneqn(ineq2, rat(factor2)));
01897 tLTalpha = canonPred(thm2);
01898 ineq2 = tLTalpha.getExpr();
01899 }
01900
01901
01902
01903 Expr beta(ineq1[0]);
01904 Expr alpha(ineq2[1]);
01905
01906 if(isLE(ineq1) && isLE(ineq2) && alpha == beta) {
01907 Theorem result = d_rules->realShadowEq(betaLTt, tLTalpha);
01908 TRACE("arith ineq", "normalizeProjectIneqs => ", result, " }");
01909 return result;
01910 }
01911
01912
01913
01914
01915
01916
01917
01918
01919
01920
01921
01922 Theorem result = d_rules->realShadow(betaLTt, tLTalpha);
01923
01924
01925
01926
01927
01928
01929 Expr e(result.getExpr());
01930
01931 if(!(e[0].isRational() && e[0].getRational() == 0))
01932 result = iffMP(result, d_rules->rightMinusLeft(e));
01933 result = canonPred(result);
01934
01935
01936 Expr right = result.getExpr()[1];
01937
01938 if (right.isRational())
01939 result = iffMP(result, d_rules->constPredicate(result.getExpr()));
01940 else
01941 result = normalize(result);
01942 TRACE("arith ineq", "normalizeProjectIneqs => ", result, " }");
01943 return result;
01944 }
01945
01946 Rational TheoryArithOld::currentMaxCoefficient(Expr var)
01947 {
01948
01949 if (var.getType() == d_realType) return -100;
01950
01951
01952 ExprMap<Rational>::iterator findMaxLeft = maxCoefficientLeft.find(var);
01953 Rational leftMax = -1;
01954 if (findMaxLeft != maxCoefficientLeft.end())
01955 leftMax = (*findMaxLeft).second;
01956
01957
01958 ExprMap<Rational>::iterator findMaxRight = maxCoefficientRight.find(var);
01959 Rational rightMax = -1;
01960 if (findMaxRight != maxCoefficientRight.end())
01961 rightMax = (*findMaxRight).second;
01962
01963
01964
01965
01966
01967 Rational returnValue;
01968 if (leftMax == -1) returnValue = rightMax;
01969 else if (rightMax == -1) returnValue = leftMax;
01970 else if (leftMax < rightMax) returnValue = rightMax;
01971 else returnValue = leftMax;
01972
01973 TRACE("arith stats", "max coeff of ", var.toString(), ": " + returnValue.toString() + "(left=" + leftMax.toString() + ",right=" + rightMax.toString());
01974
01975 return returnValue;
01976 }
01977
01978 void TheoryArithOld::fixCurrentMaxCoefficient(Expr var, Rational max) {
01979 fixedMaxCoefficient[var] = max;
01980 }
01981
01982 void TheoryArithOld::selectSmallestByCoefficient(const vector<Expr>& input, vector<Expr>& output) {
01983
01984
01985 output.clear();
01986
01987
01988 Expr best_variable = input[0];
01989 Rational best_coefficient = currentMaxCoefficient(best_variable);
01990 output.push_back(best_variable);
01991
01992 for(unsigned int i = 1; i < input.size(); i ++) {
01993
01994
01995 Expr current_variable = input[i];
01996
01997 Rational current_coefficient = currentMaxCoefficient(current_variable);
01998
01999
02000 if ((current_coefficient < best_coefficient)) {
02001 best_variable = current_variable;
02002 best_coefficient = current_coefficient;
02003 output.clear();
02004 }
02005
02006
02007 if (current_coefficient == best_coefficient)
02008 output.push_back(current_variable);
02009 }
02010
02011
02012
02013 }
02014
02015 Expr TheoryArithOld::pickMonomial(const Expr& right)
02016 {
02017 DebugAssert(isPlus(right), "TheoryArithOld::pickMonomial: Wrong Kind: " +
02018 right.toString());
02019 if(theoryCore()->getFlags()["var-order"].getBool()) {
02020 Expr::iterator i = right.begin();
02021 Expr isolatedMonomial = right[1];
02022
02023
02024
02025 for(++i; i != right.end(); ++i)
02026 if(lessThanVar(isolatedMonomial,*i))
02027 isolatedMonomial = *i;
02028 return isolatedMonomial;
02029 }
02030
02031 ExprMap<Expr> var2monomial;
02032 vector<Expr> vars;
02033 Expr::iterator i = right.begin(), iend = right.end();
02034 for(;i != iend; ++i) {
02035 if(i->isRational())
02036 continue;
02037 Expr c, var;
02038 separateMonomial(*i, c, var);
02039 var2monomial[var] = *i;
02040 vars.push_back(var);
02041 }
02042
02043 vector<Expr> largest;
02044 d_graph.selectLargest(vars, largest);
02045 DebugAssert(0 < largest.size(),
02046 "TheoryArithOld::pickMonomial: selectLargest: failed!!!!");
02047
02048
02049 vector<Expr> largest_small_coeff;
02050 selectSmallestByCoefficient(largest, largest_small_coeff);
02051 DebugAssert(0 < largest_small_coeff.size(), "TheoryArithOld::pickMonomial: selectLargestByCOefficient: failed!!!!");
02052
02053 size_t pickedVar = 0;
02054
02055
02056
02057 size_t size = largest_small_coeff.size();
02058 int minProjections = -1;
02059 if (size > 1)
02060 for(size_t k=0; k< size; ++k) {
02061 const Expr& var(largest_small_coeff[k]), monom(var2monomial[var]);
02062
02063 int nRight = (d_countRight.count(var) > 0)? d_countRight[var] : 0;
02064 int nLeft = (d_countLeft.count(var) > 0)? d_countLeft[var] : 0;
02065 int n(nRight*nLeft);
02066 TRACE("arith ineq", "pickMonomial: var=", var,
02067 ", nRight="+int2string(nRight)+", nLeft="+int2string(nLeft));
02068 if(minProjections < 0 || minProjections > n) {
02069 minProjections = n;
02070 pickedVar = k;
02071 }
02072 TRACE("arith ineq", "Number of projections for "+var.toString()+" = ", n, "");
02073 }
02074
02075
02076 const Expr& largestVar = largest_small_coeff[pickedVar];
02077
02078
02079
02080
02081 for(size_t k = 0; k < vars.size(); ++k) {
02082 if(vars[k] != largestVar)
02083 d_graph.addEdge(largestVar, vars[k]);
02084 }
02085
02086 TRACE("arith buffer", "picked var : ", var2monomial[largestVar].toString(), "");
02087
02088 return var2monomial[largestVar];
02089 }
02090
02091 void TheoryArithOld::VarOrderGraph::addEdge(const Expr& e1, const Expr& e2)
02092 {
02093 TRACE("arith var order", "addEdge("+e1.toString()+" > ", e2, ")");
02094 DebugAssert(e1 != e2, "TheoryArithOld::VarOrderGraph::addEdge("
02095 +e1.toString()+", "+e2.toString()+")");
02096 d_edges[e1].push_back(e2);
02097 }
02098
02099
02100
02101 bool TheoryArithOld::VarOrderGraph::lessThan(const Expr& e1, const Expr& e2)
02102 {
02103 d_cache.clear();
02104
02105 return dfs(e1,e2);
02106 }
02107
02108
02109 bool TheoryArithOld::VarOrderGraph::dfs(const Expr& e1, const Expr& e2)
02110 {
02111 if(e1 == e2)
02112 return true;
02113 if(d_cache.count(e2) > 0)
02114 return false;
02115 if(d_edges.count(e2) == 0)
02116 return false;
02117 d_cache[e2] = true;
02118 vector<Expr>& e2Edges = d_edges[e2];
02119 vector<Expr>::iterator i = e2Edges.begin();
02120 vector<Expr>::iterator iend = e2Edges.end();
02121
02122 for(; i != iend && !dfs(e1,*i); ++i);
02123 return (i != iend);
02124 }
02125
02126 void TheoryArithOld::VarOrderGraph::dfs(const Expr& v, vector<Expr>& output_list)
02127 {
02128 TRACE("arith shared", "dfs(", v.toString(), ")");
02129
02130
02131 if (d_cache.count(v) > 0) return;
02132
02133
02134 if(d_edges.count(v) != 0) {
02135
02136 vector<Expr>& vEdges = d_edges[v];
02137 vector<Expr>::iterator e = vEdges.begin();
02138 vector<Expr>::iterator e_end = vEdges.end();
02139 while (e != e_end) {
02140 dfs(*e, output_list);
02141 e ++;
02142 }
02143 }
02144
02145
02146 d_cache[v] = true;
02147 output_list.push_back(v);
02148 }
02149
02150 void TheoryArithOld::VarOrderGraph::getVerticesTopological(vector<Expr>& output_list)
02151 {
02152
02153 d_cache.clear();
02154 output_list.clear();
02155
02156
02157 ExprMap< vector<Expr> >::iterator v_it = d_edges.begin();
02158 ExprMap< vector<Expr> >::iterator v_it_end = d_edges.end();
02159 while (v_it != v_it_end)
02160 {
02161
02162 dfs(v_it->first, output_list);
02163
02164 v_it ++;
02165 }
02166 }
02167
02168 void TheoryArithOld::VarOrderGraph::selectSmallest(vector<Expr>& v1,
02169 vector<Expr>& v2)
02170 {
02171 int v1Size = v1.size();
02172 vector<bool> v3(v1Size);
02173 for(int j=0; j < v1Size; ++j)
02174 v3[j] = false;
02175
02176 for(int j=0; j < v1Size; ++j) {
02177 if(v3[j]) continue;
02178 for(int i =0; i < v1Size; ++i) {
02179 if((i == j) || v3[i])
02180 continue;
02181 if(lessThan(v1[i],v1[j])) {
02182 v3[j] = true;
02183 break;
02184 }
02185 }
02186 }
02187 vector<Expr> new_v1;
02188
02189 for(int j = 0; j < v1Size; ++j)
02190 if(!v3[j]) v2.push_back(v1[j]);
02191 else new_v1.push_back(v1[j]);
02192 v1 = new_v1;
02193 }
02194
02195
02196 void TheoryArithOld::VarOrderGraph::selectLargest(const vector<Expr>& v1,
02197 vector<Expr>& v2)
02198 {
02199 int v1Size = v1.size();
02200 vector<bool> v3(v1Size);
02201 for(int j=0; j < v1Size; ++j)
02202 v3[j] = false;
02203
02204 for(int j=0; j < v1Size; ++j) {
02205 if(v3[j]) continue;
02206 for(int i =0; i < v1Size; ++i) {
02207 if((i == j) || v3[i])
02208 continue;
02209 if(lessThan(v1[j],v1[i])) {
02210 v3[j] = true;
02211 break;
02212 }
02213 }
02214 }
02215
02216 for(int j = 0; j < v1Size; ++j)
02217 if(!v3[j]) v2.push_back(v1[j]);
02218 }
02219
02220
02221
02222
02223
02224
02225 TheoryArithOld::TheoryArithOld(TheoryCore* core)
02226 : TheoryArith(core, "ArithmeticOld"),
02227 d_diseq(core->getCM()->getCurrentContext()),
02228 d_diseqIdx(core->getCM()->getCurrentContext(), 0, 0),
02229 diseqSplitAlready(core->getCM()->getCurrentContext()),
02230 d_inModelCreation(core->getCM()->getCurrentContext(), false, 0),
02231 d_freeConstDB(core->getCM()->getCurrentContext()),
02232 d_buffer_0(core->getCM()->getCurrentContext()),
02233 d_buffer_1(core->getCM()->getCurrentContext()),
02234 d_buffer_2(core->getCM()->getCurrentContext()),
02235 d_buffer_3(core->getCM()->getCurrentContext()),
02236
02237 d_bufferIdx_0(core->getCM()->getCurrentContext(), 0, 0),
02238 d_bufferIdx_1(core->getCM()->getCurrentContext(), 0, 0),
02239 d_bufferIdx_2(core->getCM()->getCurrentContext(), 0, 0),
02240 d_bufferIdx_3(core->getCM()->getCurrentContext(), 0, 0),
02241 diff_logic_size(core->getCM()->getCurrentContext(), 0, 0),
02242 d_bufferThres(&(core->getFlags()["ineq-delay"].getInt())),
02243 d_splitSign(&(core->getFlags()["nonlinear-sign-split"].getBool())),
02244 d_grayShadowThres(&(core->getFlags()["grayshadow-threshold"].getInt())),
02245 d_countRight(core->getCM()->getCurrentContext()),
02246 d_countLeft(core->getCM()->getCurrentContext()),
02247 d_sharedTerms(core->getCM()->getCurrentContext()),
02248 d_sharedTermsList(core->getCM()->getCurrentContext()),
02249 d_sharedVars(core->getCM()->getCurrentContext()),
02250 bufferedInequalities(core->getCM()->getCurrentContext()),
02251 termLowerBound(core->getCM()->getCurrentContext()),
02252 termLowerBoundThm(core->getCM()->getCurrentContext()),
02253 termUpperBound(core->getCM()->getCurrentContext()),
02254 termUpperBoundThm(core->getCM()->getCurrentContext()),
02255 alreadyProjected(core->getCM()->getCurrentContext()),
02256 dontBuffer(core->getCM()->getCurrentContext()),
02257 diffLogicOnly(core->getCM()->getCurrentContext(), true, 0),
02258 diffLogicGraph(0, core, 0, core->getCM()->getCurrentContext()),
02259 shared_index_1(core->getCM()->getCurrentContext(), 0, 0),
02260 shared_index_2(core->getCM()->getCurrentContext(), 0, 0),
02261 termUpperBounded(core->getCM()->getCurrentContext()),
02262 termLowerBounded(core->getCM()->getCurrentContext()),
02263 termConstrainedBelow(core->getCM()->getCurrentContext()),
02264 termConstrainedAbove(core->getCM()->getCurrentContext())
02265 {
02266 IF_DEBUG(d_diseq.setName("CDList[TheoryArithOld::d_diseq]");)
02267 IF_DEBUG(d_buffer_0.setName("CDList[TheoryArithOld::d_buffer_0]");)
02268 IF_DEBUG(d_buffer_1.setName("CDList[TheoryArithOld::d_buffer_1]");)
02269 IF_DEBUG(d_buffer_2.setName("CDList[TheoryArithOld::d_buffer_2]");)
02270 IF_DEBUG(d_buffer_3.setName("CDList[TheoryArithOld::d_buffer_3]");)
02271 IF_DEBUG(d_bufferIdx_1.setName("CDList[TheoryArithOld::d_bufferIdx_0]");)
02272 IF_DEBUG(d_bufferIdx_1.setName("CDList[TheoryArithOld::d_bufferIdx_1]");)
02273 IF_DEBUG(d_bufferIdx_2.setName("CDList[TheoryArithOld::d_bufferIdx_2]");)
02274 IF_DEBUG(d_bufferIdx_3.setName("CDList[TheoryArithOld::d_bufferIdx_3]");)
02275
02276 getEM()->newKind(REAL, "_REAL", true);
02277 getEM()->newKind(INT, "_INT", true);
02278 getEM()->newKind(SUBRANGE, "_SUBRANGE", true);
02279
02280 getEM()->newKind(UMINUS, "_UMINUS");
02281 getEM()->newKind(PLUS, "_PLUS");
02282 getEM()->newKind(MINUS, "_MINUS");
02283 getEM()->newKind(MULT, "_MULT");
02284 getEM()->newKind(DIVIDE, "_DIVIDE");
02285 getEM()->newKind(POW, "_POW");
02286 getEM()->newKind(INTDIV, "_INTDIV");
02287 getEM()->newKind(MOD, "_MOD");
02288 getEM()->newKind(LT, "_LT");
02289 getEM()->newKind(LE, "_LE");
02290 getEM()->newKind(GT, "_GT");
02291 getEM()->newKind(GE, "_GE");
02292 getEM()->newKind(IS_INTEGER, "_IS_INTEGER");
02293 getEM()->newKind(NEGINF, "_NEGINF");
02294 getEM()->newKind(POSINF, "_POSINF");
02295 getEM()->newKind(DARK_SHADOW, "_DARK_SHADOW");
02296 getEM()->newKind(GRAY_SHADOW, "_GRAY_SHADOW");
02297
02298 getEM()->newKind(REAL_CONST, "_REAL_CONST");
02299
02300 d_kinds.push_back(REAL);
02301 d_kinds.push_back(INT);
02302 d_kinds.push_back(SUBRANGE);
02303 d_kinds.push_back(IS_INTEGER);
02304 d_kinds.push_back(UMINUS);
02305 d_kinds.push_back(PLUS);
02306 d_kinds.push_back(MINUS);
02307 d_kinds.push_back(MULT);
02308 d_kinds.push_back(DIVIDE);
02309 d_kinds.push_back(POW);
02310 d_kinds.push_back(INTDIV);
02311 d_kinds.push_back(MOD);
02312 d_kinds.push_back(LT);
02313 d_kinds.push_back(LE);
02314 d_kinds.push_back(GT);
02315 d_kinds.push_back(GE);
02316 d_kinds.push_back(RATIONAL_EXPR);
02317 d_kinds.push_back(NEGINF);
02318 d_kinds.push_back(POSINF);
02319 d_kinds.push_back(DARK_SHADOW);
02320 d_kinds.push_back(GRAY_SHADOW);
02321 d_kinds.push_back(REAL_CONST);
02322
02323 registerTheory(this, d_kinds, true);
02324
02325 d_rules = createProofRulesOld();
02326 diffLogicGraph.setRules(d_rules);
02327 diffLogicGraph.setArith(this);
02328
02329 d_realType = Type(getEM()->newLeafExpr(REAL));
02330 d_intType = Type(getEM()->newLeafExpr(INT));
02331
02332
02333 Theorem thm_exists_zero = getCommonRules()->varIntroSkolem(rat(0));
02334 zero = thm_exists_zero.getExpr()[1];
02335 }
02336
02337
02338
02339 TheoryArithOld::~TheoryArithOld() {
02340 if(d_rules != NULL) delete d_rules;
02341
02342 for(ExprMap<CDList<Ineq> *>::iterator i=d_inequalitiesRightDB.begin(),
02343 iend=d_inequalitiesRightDB.end(); i!=iend; ++i) {
02344 delete (i->second);
02345 free(i->second);
02346 }
02347 for(ExprMap<CDList<Ineq> *>::iterator i=d_inequalitiesLeftDB.begin(),
02348 iend=d_inequalitiesLeftDB.end(); i!=iend; ++i) {
02349 delete (i->second);
02350 free (i->second);
02351 }
02352 unregisterTheory(this, d_kinds, true);
02353 }
02354
02355 void TheoryArithOld::collectVars(const Expr& e, vector<Expr>& vars,
02356 set<Expr>& cache) {
02357
02358 if(cache.count(e) > 0) return;
02359
02360 cache.insert(e);
02361 if(isLeaf(e)) vars.push_back(e);
02362 else
02363 for(Expr::iterator i=e.begin(), iend=e.end(); i!=iend; ++i)
02364 collectVars(*i, vars, cache);
02365 }
02366
02367 void
02368 TheoryArithOld::processFiniteInterval
02369 (const Theorem& alphaLEax,
02370 const Theorem& bxLEbeta) {
02371 const Expr& ineq1(alphaLEax.getExpr());
02372 const Expr& ineq2(bxLEbeta.getExpr());
02373 DebugAssert(isLE(ineq1), "TheoryArithOld::processFiniteInterval: ineq1 = "
02374 +ineq1.toString());
02375 DebugAssert(isLE(ineq2), "TheoryArithOld::processFiniteInterval: ineq2 = "
02376 +ineq2.toString());
02377
02378 if(!isInteger(ineq1[0])
02379 || !isInteger(ineq1[1])
02380 || !isInteger(ineq2[0])
02381 || !isInteger(ineq2[1]))
02382 return;
02383
02384 const Expr& ax = ineq1[1];
02385 const Expr& bx = ineq2[0];
02386 DebugAssert(!isPlus(ax) && !isRational(ax),
02387 "TheoryArithOld::processFiniteInterval:\n ax = "+ax.toString());
02388 DebugAssert(!isPlus(bx) && !isRational(bx),
02389 "TheoryArithOld::processFiniteInterval:\n bx = "+bx.toString());
02390 Expr a = isMult(ax)? ax[0] : rat(1);
02391 Expr b = isMult(bx)? bx[0] : rat(1);
02392
02393 Theorem thm1(alphaLEax), thm2(bxLEbeta);
02394
02395 if(a != b) {
02396 thm1 = canonPred(iffMP(alphaLEax, d_rules->multIneqn(ineq1, b)));
02397 thm2 = canonPred(iffMP(bxLEbeta, d_rules->multIneqn(ineq2, a)));
02398 }
02399
02400 const Expr& alphaLEt = thm1.getExpr();
02401 const Expr& alpha = alphaLEt[0];
02402 const Expr& t = alphaLEt[1];
02403 const Expr& beta = thm2.getExpr()[1];
02404 Expr c = canon(beta - alpha).getRHS();
02405
02406 if(c.isRational() && c.getRational() >= 1) {
02407
02408
02409
02410 Theorem bEQac = symmetryRule(canon(alpha + c));
02411
02412 vector<unsigned> changed;
02413 vector<Theorem> thms;
02414 changed.push_back(1);
02415 thms.push_back(bEQac);
02416 Theorem tLEac = substitutivityRule(thm2.getExpr(), changed, thms);
02417 tLEac = iffMP(thm2, tLEac);
02418
02419 Theorem isInta(isIntegerThm(alpha));
02420 Theorem isIntt(isIntegerThm(t));
02421 if (d_sharedTerms.find(thm1.getExpr()[1]) != d_sharedTerms.end())
02422 enqueueFact(d_rules->finiteInterval(thm1, tLEac, isInta, isIntt));
02423 }
02424 }
02425
02426
02427 void
02428 TheoryArithOld::processFiniteIntervals(const Expr& x) {
02429
02430 if(!isInteger(x)) return;
02431
02432 ExprMap<CDList<Ineq> *>::iterator iLeft, iRight;
02433 iLeft = d_inequalitiesLeftDB.find(x);
02434 if(iLeft == d_inequalitiesLeftDB.end()) return;
02435 iRight = d_inequalitiesRightDB.find(x);
02436 if(iRight == d_inequalitiesRightDB.end()) return;
02437
02438 CDList<Ineq>& ineqsLeft = *(iLeft->second);
02439 CDList<Ineq>& ineqsRight = *(iRight->second);
02440
02441 size_t sizeLeft = ineqsLeft.size();
02442 size_t sizeRight = ineqsRight.size();
02443
02444 for(size_t l=0; l<sizeLeft; ++l)
02445 for(size_t r=0; r<sizeRight; ++r)
02446 processFiniteInterval(ineqsRight[r], ineqsLeft[l]);
02447 }
02448
02449
02450
02451
02452
02453 void
02454 TheoryArithOld::setupRec(const Expr& e) {
02455 if(e.hasFind()) return;
02456
02457 for (int k = 0; k < e.arity(); ++k) {
02458 setupRec(e[k]);
02459 }
02460
02461 e.setFind(reflexivityRule(e));
02462 e.setEqNext(reflexivityRule(e));
02463
02464 setup(e);
02465 }
02466
02467
02468 void TheoryArithOld::addSharedTerm(const Expr& e) {
02469 if (d_sharedTerms.find(e) == d_sharedTerms.end()) {
02470 d_sharedTerms[e] = true;
02471 d_sharedTermsList.push_back(e);
02472
02473
02474
02475
02476
02477
02478
02479
02480
02481
02482 }
02483 }
02484
02485
02486 void TheoryArithOld::assertFact(const Theorem& e)
02487 {
02488 TRACE("arith assert", "assertFact(", e.getExpr().toString(), ")");
02489
02490
02491 for (unsigned i = 0; i < multiplicativeSignSplits.size(); i ++)
02492 enqueueFact(multiplicativeSignSplits[i]);
02493 multiplicativeSignSplits.clear();
02494
02495 const Expr& expr = e.getExpr();
02496 if (expr.isNot() && expr[0].isEq()) {
02497 IF_DEBUG(debugger.counter("[arith] received disequalities")++;)
02498
02499
02500
02501
02502
02503
02504
02505
02506
02507
02508
02509
02510
02511
02512
02513
02514
02515
02516
02517
02518
02519
02520
02521
02522
02523
02524
02525
02526
02527
02528
02529
02530
02531
02532
02533
02534
02535
02536
02537
02538
02539 d_diseq.push_back(e);
02540 }
02541 else if (!expr.isEq()){
02542 if (expr.isNot()) {
02543
02544
02545 if (expr[0].getKind() == IS_INTEGER) {
02546 expr[0][0].addToNotify(this, expr[0]);
02547 }
02548
02549
02550
02551
02552
02553
02554
02555
02556
02557
02558 }
02559 else if(isDarkShadow(expr)) {
02560 enqueueFact(d_rules->expandDarkShadow(e));
02561 IF_DEBUG(debugger.counter("received DARK_SHADOW")++;)
02562 }
02563 else if(isGrayShadow(expr)) {
02564 IF_DEBUG(debugger.counter("received GRAY_SHADOW")++;)
02565 const Rational& c1 = expr[2].getRational();
02566 const Rational& c2 = expr[3].getRational();
02567
02568
02569 if (*d_grayShadowThres > -1 && (c2 - c1 > *d_grayShadowThres)) {
02570 setIncomplete("Some gray shadows ignored due to threshold");
02571 return;
02572 }
02573
02574 const Expr& v = expr[0];
02575 const Expr& ee = expr[1];
02576 if(c1 == c2)
02577 enqueueFact(d_rules->expandGrayShadow0(e));
02578 else {
02579 Theorem gThm(e);
02580
02581 if(ee.isRational() && isMult(v)
02582 && v[0].isRational() && v[0].getRational() >= 2) {
02583 IF_DEBUG(debugger.counter("reduced const GRAY_SHADOW")++;)
02584 gThm = d_rules->grayShadowConst(e);
02585 }
02586
02587 const Expr& g = gThm.getExpr();
02588 if(g.isFalse())
02589 setInconsistent(gThm);
02590 else if(g[2].getRational() == g[3].getRational())
02591 enqueueFact(d_rules->expandGrayShadow0(gThm));
02592 else if(g[3].getRational() - g[2].getRational() <= 5) {
02593
02594 enqueueFact(d_rules->expandGrayShadow(gThm));
02595
02596 Theorem thm2 = d_rules->splitGrayShadowSmall(gThm);
02597 enqueueFact(thm2);
02598 }
02599 else {
02600
02601 enqueueFact(d_rules->expandGrayShadow(gThm));
02602
02603 Theorem thm2 = d_rules->splitGrayShadow(gThm);
02604 enqueueFact(thm2);
02605
02606
02607
02608
02609
02610
02611
02612
02613
02614
02615
02616
02617
02618
02619
02620
02621
02622 }
02623 }
02624 }
02625 else {
02626 DebugAssert(isLE(expr) || isLT(expr) || isIntPred(expr),
02627 "expected LE or LT: "+expr.toString());
02628 if(isLE(expr) || isLT(expr)) {
02629 IF_DEBUG(debugger.counter("recevied inequalities")++;)
02630
02631
02632
02633
02634
02635
02636
02637
02638
02639
02640
02641
02642
02643 addToBuffer(e);
02644
02645 unsigned total_buf_size = d_buffer_0.size() + d_buffer_1.size() + d_buffer_2.size() + d_buffer_3.size();
02646 unsigned processed = d_bufferIdx_0 + d_bufferIdx_1 + d_bufferIdx_2 + d_bufferIdx_3;
02647 TRACE("arith ineq", "buffer.size() = ", total_buf_size,
02648 ", index="+int2string(processed)
02649 +", threshold="+int2string(*d_bufferThres));
02650
02651 if(!diffLogicOnly && *d_bufferThres >= 0 && (total_buf_size > *d_bufferThres + processed) && !d_inModelCreation) {
02652 processBuffer();
02653 }
02654 } else {
02655 IF_DEBUG(debugger.counter("arith IS_INTEGER")++;)
02656 if (!isInteger(expr[0])) {
02657 enqueueFact(d_rules->IsIntegerElim(e));
02658 }
02659 }
02660 }
02661 }
02662 else {
02663 IF_DEBUG(debugger.counter("[arith] received t1=t2")++;)
02664
02665
02666
02667
02668
02669
02670
02671
02672
02673
02674
02675
02676
02677
02678
02679
02680
02681
02682
02683 }
02684 }
02685
02686
02687 void TheoryArithOld::checkSat(bool fullEffort)
02688 {
02689
02690
02691
02692 TRACE("arith checksat", "checksat(fullEffort = ", fullEffort? "true, modelCreation = " : "false, modelCreation = ", (d_inModelCreation ? "true)" : "false)"));
02693 TRACE("arith ineq", "TheoryArithOld::checkSat(fullEffort=",
02694 fullEffort? "true" : "false", ")");
02695 if (fullEffort) {
02696
02697
02698 if (!inconsistent())
02699 processBuffer();
02700
02701
02702 int total_buffer_size = d_buffer_0.size() + d_buffer_1.size() + d_buffer_2.size() + d_buffer_3.size();
02703
02704 int constrained_vars = 0;
02705 if (!inconsistent() && total_buffer_size > 0)
02706 constrained_vars = computeTermBounds();
02707
02708 bool something_enqueued = false;
02709
02710 if (d_inModelCreation || (!inconsistent() && total_buffer_size > 0 && constrained_vars > 0)) {
02711
02712 if (d_inModelCreation) d_diseqIdx = 0;
02713
02714
02715 for(; d_diseqIdx < d_diseq.size(); d_diseqIdx = d_diseqIdx+1) {
02716 TRACE("model", "[arith] refining diseq: ", d_diseq[d_diseqIdx].getExpr() , "");
02717
02718
02719 Theorem diseqThm = d_diseq[d_diseqIdx];
02720 Expr diseq = diseqThm.getExpr();
02721
02722
02723 if (diseqSplitAlready.find(diseq) != diseqSplitAlready.end()) continue;
02724
02725
02726 Expr eq = diseq[0];
02727
02728
02729 Expr lhs = eq[0];
02730 Expr rhs = eq[1];
02731 DebugAssert(lhs.hasFind() && rhs.hasFind(), "Part of dis-equality has no find!");
02732 lhs = find(lhs).getRHS();
02733 rhs = find(rhs).getRHS();
02734
02735
02736
02737 if (lhs.isRational() && rhs.isRational()) {
02738 TRACE("arith diseq", "disequality already evaluated : ", diseq.toString(), "");
02739 continue;
02740 }
02741
02742
02743
02744 if (!d_inModelCreation) {
02745
02746 if (!isConstrained(lhs) || !isConstrained(rhs)) continue;
02747 if (getUpperBound(lhs) < getLowerBound(rhs)) continue;
02748 if (getUpperBound(rhs) < getLowerBound(lhs)) continue;
02749 }
02750
02751 TRACE("arith ineq", "[arith] refining diseq: ", d_diseq[d_diseqIdx].getExpr() , "");
02752
02753
02754 enqueueFact(d_rules->diseqToIneq(diseqThm));
02755 something_enqueued = true;
02756
02757
02758 diseqSplitAlready[diseq] = true;
02759 }
02760 }
02761
02762
02763 if (!something_enqueued && !inconsistent() && total_buffer_size > 0 && constrained_vars > 0) {
02764 unsigned size = d_sharedTermsList.size();
02765
02766 Expr t1, t2;
02767 Expr t1_find, t2_find;
02768
02769 TRACE("arith shared", "expanding on shared term equalities","","");
02770
02771 TheoryArithOld::DifferenceLogicGraph::EpsRational t1_find_lowerBound;
02772 TheoryArithOld::DifferenceLogicGraph::EpsRational t1_find_upperBound;
02773
02774
02775 if (shared_index_1 < size) {
02776 t1 = d_sharedTermsList[shared_index_1];
02777 DebugAssert(!t1.isNull(), "t1 is null!");
02778 DebugAssert(t1.hasFind(), "t1 has no find");
02779 t1_find = find(t1).getRHS();
02780 t1_find_lowerBound = getLowerBound(t1_find);
02781 t1_find_upperBound = getUpperBound(t1_find);
02782 }
02783 while (!something_enqueued && !inconsistent() && shared_index_1 < size) {
02784
02785
02786 shared_index_2 = shared_index_2 + 1;
02787
02788
02789 if (shared_index_2 >= shared_index_1 || t1_find != t1 || !isConstrained(t1_find)) {
02790
02791 shared_index_2 = 0;
02792 t2 = d_sharedTermsList[0];
02793 DebugAssert(!t2.isNull(), "t2 is null!");
02794
02795
02796 shared_index_1 = shared_index_1 + 1;
02797 while (shared_index_1 < size) {
02798 t1 = d_sharedTermsList[shared_index_1];
02799 DebugAssert(!t1.isNull(), "t1 is null!");
02800 DebugAssert(t1.hasFind(), "t1 has no find");
02801 t1_find = find(t1).getRHS();
02802 if (t1_find != t1 || !isConstrained(t1_find)) {
02803 shared_index_1 = shared_index_1 + 1;
02804 continue;
02805 } else {
02806 t1_find_lowerBound = getLowerBound(t1_find);
02807 t1_find_upperBound = getUpperBound(t1_find);
02808 break;
02809 }
02810 }
02811 if (shared_index_1 >= size) break;
02812 } else {
02813 t2 = d_sharedTermsList[shared_index_2];
02814 DebugAssert(!t2.isNull(), "t2 is null!");
02815 }
02816
02817 TRACE("arith shared", "comparing : ", int2string(shared_index_1) + " with", int2string(shared_index_2));
02818
02819 DebugAssert(t2.hasFind(), "t2 has no find");
02820 t2_find = find(t2).getRHS();
02821 if (t2_find != t2) continue;
02822 if (t2_find == t1_find) continue;
02823 if (t2_find.isRational() && t1_find.isRational()) continue;
02824 if (!isConstrained(t2_find)) continue;
02825 if (getUpperBound(t2_find) < t1_find_lowerBound) continue;
02826 if (t1_find_upperBound < getLowerBound(t2_find)) continue;
02827
02828 TRACE("arith shared", "comparing : ", int2string(shared_index_1) + " with ", int2string(shared_index_2) + " (of " + int2string(size) + ")");
02829 TRACE("arith shared", "checking shared term eq for ", t1.toString() + " and ", t2.toString());
02830
02831
02832 if (!isIntegerThm(t1_find).isNull() && !isIntegerThm(t2_find).isNull()) {
02833
02834 Expr eq = t2_find.eqExpr(t1_find);
02835
02836 Theorem simplifyEq = canonSimp(eq);
02837 if (simplifyEq.getRHS().isBoolConst()) {
02838
02839
02840 DebugAssert(simplifyEq.getRHS().isFalse() || isNonlinearEq(eq), "Simplification of the shared equality is true!!!" + eq.toString());
02841 continue;
02842 }
02843
02844 addSplitter(eq, 0);
02845
02846 something_enqueued = true;
02847 TRACE("arith shared", "adding shared term eq for ", eq.toString(), "");
02848 }
02849 }
02850 }
02851
02852 IF_DEBUG(
02853 {
02854 bool dejans_printouts = false;
02855 if (dejans_printouts) {
02856 cerr << "Disequalities after CheckSat" << endl;
02857 for (unsigned i = 0; i < d_diseq.size(); i ++) {
02858 Expr diseq = d_diseq[i].getExpr();
02859 Expr d_find = find(diseq[0]).getRHS();
02860 cerr << diseq.toString() << ":" << d_find.toString() << endl;
02861 }
02862 cerr << "Arith Buffer after CheckSat (0)" << endl;
02863 for (unsigned i = 0; i < d_buffer_0.size(); i ++) {
02864 Expr ineq = d_buffer_0[i].getExpr();
02865 Expr rhs = find(ineq[1]).getRHS();
02866 cerr << ineq.toString() << ":" << rhs.toString() << endl;
02867 }
02868 cerr << "Arith Buffer after CheckSat (1)" << endl;
02869 for (unsigned i = 0; i < d_buffer_1.size(); i ++) {
02870 Expr ineq = d_buffer_1[i].getExpr();
02871 Expr rhs = find(ineq[1]).getRHS();
02872 cerr << ineq.toString() << ":" << rhs.toString() << endl;
02873 }
02874 cerr << "Arith Buffer after CheckSat (2)" << endl;
02875 for (unsigned i = 0; i < d_buffer_2.size(); i ++) {
02876 Expr ineq = d_buffer_2[i].getExpr();
02877 Expr rhs = find(ineq[1]).getRHS();
02878 cerr << ineq.toString() << ":" << rhs.toString() << endl;
02879 }
02880 cerr << "Arith Buffer after CheckSat (3)" << endl;
02881 for (unsigned i = 0; i < d_buffer_3.size(); i ++) {
02882 Expr ineq = d_buffer_3[i].getExpr();
02883 Expr rhs = find(ineq[1]).getRHS();
02884 cerr << ineq.toString() << ":" << rhs.toString() << endl;
02885 }
02886 }
02887 }
02888 )
02889 }
02890 }
02891
02892
02893
02894 void TheoryArithOld::refineCounterExample()
02895 {
02896 d_inModelCreation = true;
02897 TRACE("model", "refineCounterExample[TheoryArithOld] ", "", "{");
02898 CDMap<Expr, bool>::iterator it = d_sharedTerms.begin(), it2,
02899 iend = d_sharedTerms.end();
02900
02901
02902
02903 for(; it!=iend; ++it) {
02904
02905 Expr e1 = (*it).first;
02906 for(it2 = it, ++it2; it2!=iend; ++it2) {
02907 Expr e2 = (*it2).first;
02908 DebugAssert(isReal(getBaseType(e1)),
02909 "TheoryArithOld::refineCounterExample: e1 = "+e1.toString()
02910 +"\n type(e1) = "+e1.getType().toString());
02911 if(findExpr(e1) != findExpr(e2)) {
02912 DebugAssert(isReal(getBaseType(e2)),
02913 "TheoryArithOld::refineCounterExample: e2 = "+e2.toString()
02914 +"\n type(e2) = "+e2.getType().toString());
02915 Expr eq = simplifyExpr(e1.eqExpr(e2));
02916 if (!eq.isBoolConst()) {
02917 addSplitter(eq);
02918 }
02919 }
02920 }
02921 }
02922 TRACE("model", "refineCounterExample[Theory::Arith] ", "", "}");
02923 }
02924
02925
02926 void
02927 TheoryArithOld::findRationalBound(const Expr& varSide, const Expr& ratSide,
02928 const Expr& var,
02929 Rational &r)
02930 {
02931 Expr c, x;
02932 separateMonomial(varSide, c, x);
02933
02934 if (!findExpr(ratSide).isRational() && isNonlinearEq(ratSide.eqExpr(rat(0))))
02935 throw ArithException("Could not generate the model due to non-linear arithmetic");
02936
02937 DebugAssert(findExpr(c).isRational(),
02938 "seperateMonomial failed");
02939 DebugAssert(findExpr(ratSide).isRational(),
02940 "smallest variable in graph, should not have variables"
02941 " in inequalities: ");
02942 DebugAssert(x == var, "separateMonomial found different variable: "
02943 + var.toString());
02944 r = findExpr(ratSide).getRational() / findExpr(c).getRational();
02945 }
02946
02947 bool
02948 TheoryArithOld::findBounds(const Expr& e, Rational& lub, Rational& glb)
02949 {
02950 bool strictLB=false, strictUB=false;
02951 bool right = (d_inequalitiesRightDB.count(e) > 0
02952 && d_inequalitiesRightDB[e]->size() > 0);
02953 bool left = (d_inequalitiesLeftDB.count(e) > 0
02954 && d_inequalitiesLeftDB[e]->size() > 0);
02955 int numRight = 0, numLeft = 0;
02956 if(right) {
02957 CDList<Ineq> * ratsLTe = d_inequalitiesRightDB[e];
02958 for(unsigned int i=0; i<ratsLTe->size(); i++) {
02959 DebugAssert((*ratsLTe)[i].varOnRHS(), "variable on wrong side!");
02960 Expr ineq = (*ratsLTe)[i].ineq().getExpr();
02961 Expr leftSide = ineq[0], rightSide = ineq[1];
02962 Rational r;
02963 findRationalBound(rightSide, leftSide, e , r);
02964 if(numRight==0 || r>glb){
02965 glb = r;
02966 strictLB = isLT(ineq);
02967 }
02968 numRight++;
02969 }
02970 TRACE("model", " =>Lower bound ", glb.toString(), "");
02971 }
02972 if(left) {
02973 CDList<Ineq> * ratsGTe = d_inequalitiesLeftDB[e];
02974 for(unsigned int i=0; i<ratsGTe->size(); i++) {
02975 DebugAssert((*ratsGTe)[i].varOnLHS(), "variable on wrong side!");
02976 Expr ineq = (*ratsGTe)[i].ineq().getExpr();
02977 Expr leftSide = ineq[0], rightSide = ineq[1];
02978 Rational r;
02979 findRationalBound(leftSide, rightSide, e, r);
02980 if(numLeft==0 || r<lub) {
02981 lub = r;
02982 strictUB = isLT(ineq);
02983 }
02984 numLeft++;
02985 }
02986 TRACE("model", " =>Upper bound ", lub.toString(), "");
02987 }
02988 if(!left && !right) {
02989 lub = 0;
02990 glb = 0;
02991 }
02992 if(!left && right) {lub = glb +2;}
02993 if(!right && left) {glb = lub-2;}
02994 DebugAssert(glb <= lub, "Greatest lower bound needs to be smaller "
02995 "than least upper bound");
02996 return strictLB;
02997 }
02998
02999 void TheoryArithOld::assignVariables(std::vector<Expr>&v)
03000 {
03001 int count = 0;
03002
03003 if (diffLogicOnly)
03004 {
03005
03006 diffLogicGraph.computeModel();
03007
03008 for (unsigned i = 0; i < v.size(); i ++) {
03009 Expr x = v[i];
03010 assignValue(x, rat(diffLogicGraph.getValuation(x)));
03011 }
03012
03013 return;
03014 }
03015
03016 while (v.size() > 0)
03017 {
03018 std::vector<Expr> bottom;
03019 d_graph.selectSmallest(v, bottom);
03020 TRACE("model", "Finding variables to assign. Iteration # ", count, "");
03021 for(unsigned int i = 0; i<bottom.size(); i++)
03022 {
03023 Expr e = bottom[i];
03024 TRACE("model", "Found: ", e, "");
03025
03026 if(e.isRational()) continue;
03027
03028 Rational lub, glb;
03029 bool strictLB;
03030 strictLB = findBounds(e, lub, glb);
03031 Rational mid;
03032 if(isInteger(e)) {
03033 if(strictLB && glb.isInteger())
03034 mid = glb + 1;
03035 else
03036 mid = ceil(glb);
03037 }
03038 else
03039 mid = (lub + glb)/2;
03040
03041 TRACE("model", "Assigning mid = ", mid, " {");
03042 assignValue(e, rat(mid));
03043 TRACE("model", "Assigned find(e) = ", findExpr(e), " }");
03044 if(inconsistent()) return;
03045 }
03046 count++;
03047 }
03048 }
03049
03050 void TheoryArithOld::computeModelBasic(const std::vector<Expr>& v)
03051 {
03052 d_inModelCreation = true;
03053 vector<Expr> reps;
03054 TRACE("model", "Arith=>computeModel ", "", "{");
03055 for(unsigned int i=0; i <v.size(); ++i) {
03056 const Expr& e = v[i];
03057 if(findExpr(e) == e) {
03058 TRACE("model", "arith variable:", e , "");
03059 reps.push_back(e);
03060 }
03061 else {
03062 TRACE("model", "arith variable:", e , "");
03063 TRACE("model", " ==> is defined by: ", findExpr(e) , "");
03064 }
03065 }
03066 assignVariables(reps);
03067 TRACE("model", "Arith=>computeModel", "", "}");
03068 d_inModelCreation = false;
03069 }
03070
03071
03072
03073 void TheoryArithOld::computeModel(const Expr& e, vector<Expr>& vars) {
03074 DebugAssert(findExpr(e).isRational(), "TheoryArithOld::computeModel("
03075 +e.toString()+")\n e is not assigned concrete value.\n"
03076 +" find(e) = "+findExpr(e).toString());
03077 assignValue(simplify(e));
03078 vars.push_back(e);
03079 }
03080
03081 Theorem TheoryArithOld::checkIntegerEquality(const Theorem& thm) {
03082
03083
03084 bool rewrite = thm.isRewrite();
03085
03086
03087 Expr eq = (rewrite ? thm.getRHS() : thm.getExpr());
03088
03089 TRACE("arith rafine", "TheoryArithOld::checkIntegerEquality(", eq, ")");
03090 DebugAssert(eq.getKind() == EQ, "checkIntegerEquality: must be an equality");
03091
03092
03093 if (!isPlus(eq[1]) && !isPlus(eq[0])) return thm;
03094 Expr old_sum = (isPlus(eq[1]) ? eq[1] : eq[0]);
03095
03096
03097 vector<Expr> children;
03098 bool const_is_integer = true;
03099 for (int i = 0; i < old_sum.arity(); i ++)
03100 if (!old_sum[i].isRational())
03101 children.push_back(old_sum[i]);
03102 else
03103 const_is_integer = old_sum[i].getRational().isInteger();
03104
03105
03106 if (const_is_integer) return thm;
03107
03108 Expr sum = (children.size() > 1 ? plusExpr(children) : children[0]);
03109
03110 Theorem isIntegerEquality = isIntegerThm(sum);
03111
03112 if (!isIntegerEquality.isNull()) {
03113 Theorem false_thm = d_rules->intEqualityRationalConstant(isIntegerEquality, eq);
03114 if (rewrite) return transitivityRule(thm, false_thm);
03115 else return iffMP(thm, false_thm);
03116 }
03117 else return thm;
03118 }
03119
03120
03121 Theorem TheoryArithOld::rafineInequalityToInteger(const Theorem& thm) {
03122
03123
03124 bool rewrite = thm.isRewrite();
03125
03126
03127 Expr ineq = (rewrite ? thm.getRHS() : thm.getExpr());
03128
03129 TRACE("arith rafine", "TheoryArithOld::rafineInequalityToInteger(", ineq, ")");
03130 DebugAssert(isIneq(ineq), "rafineInequalityToInteger: must be an inequality");
03131
03132
03133
03134
03135
03136 vector<Expr> children;
03137 if (isPlus(ineq[1])) {
03138 for (int i = 0; i < ineq[1].arity(); i ++)
03139 if (!ineq[1][i].isRational())
03140 children.push_back(ineq[1][i]);
03141 } else children.push_back(ineq[1]);
03142
03143 Expr sum = (children.size() > 1 ? plusExpr(children) : children[0]);
03144
03145 Theorem isIntegerInequality = isIntegerThm(sum);
03146
03147 if (!isIntegerInequality.isNull()) {
03148 Theorem rafine = d_rules->rafineStrictInteger(isIntegerInequality, ineq);
03149 TRACE("arith rafine", "TheoryArithOld::rafineInequalityToInteger()", "=>", rafine.getRHS());
03150 if (rewrite) return canonPredEquiv(transitivityRule(thm, rafine));
03151 else return canonPred(iffMP(thm, rafine));
03152 }
03153 else return thm;
03154 }
03155
03156
03157
03158
03159
03160
03161
03162 Theorem TheoryArithOld::normalize(const Expr& e) {
03163
03164
03165 TRACE("arith normalize", "normalize(", e, ") {");
03166 DebugAssert(e.isEq() || isIneq(e),
03167 "normalize: input must be Eq or Ineq: " + e.toString());
03168 DebugAssert(!isIneq(e) || (0 == e[0].getRational()),
03169 "normalize: if (e is ineq) then e[0] must be 0" +
03170 e.toString());
03171 if(e.isEq()) {
03172 if(e[0].isRational()) {
03173 DebugAssert(0 == e[0].getRational(),
03174 "normalize: if e is Eq and e[0] is rat then e[0]==0");
03175 }
03176 else {
03177
03178 DebugAssert(e[1].isRational() && 0 == e[1].getRational(),
03179 "normalize: if e is Eq and e[1] is rat then e[1]==0\n"
03180 " e = "+e.toString());
03181 }
03182 }
03183
03184 Expr factor;
03185 if(e[0].isRational())
03186 factor = computeNormalFactor(e[1], false);
03187 else
03188 factor = computeNormalFactor(e[0], false);
03189
03190 TRACE("arith normalize", "normalize: factor = ", factor, "");
03191 DebugAssert(factor.getRational() > 0,
03192 "normalize: factor="+ factor.toString());
03193
03194 Theorem thm(reflexivityRule(e));
03195
03196 if(factor.getRational() != 1) {
03197 int kind = e.getKind();
03198 switch(kind) {
03199 case EQ:
03200
03201 thm = d_rules->multEqn(e[0], e[1], factor);
03202
03203 thm = canonPredEquiv(thm);
03204
03205
03206
03207 thm = checkIntegerEquality(thm);
03208
03209 break;
03210 case LE:
03211 case LT:
03212 case GE:
03213 case GT: {
03214 thm = d_rules->multIneqn(e, factor);
03215
03216 thm = canonPredEquiv(thm);
03217
03218 thm = rafineInequalityToInteger(thm);
03219 break;
03220 }
03221
03222 default:
03223
03224 ostringstream ss;
03225 ss << "normalize: control should not reach here " << kind;
03226 DebugAssert(false, ss.str());
03227 break;
03228 }
03229 } else
03230 if (e.getKind() == EQ)
03231 thm = checkIntegerEquality(thm);
03232
03233 TRACE("arith normalize", "normalize => ", thm, " }");
03234 return(thm);
03235 }
03236
03237
03238 Theorem TheoryArithOld::normalize(const Theorem& eIffEqn) {
03239 if (eIffEqn.isRewrite()) return transitivityRule(eIffEqn, normalize(eIffEqn.getRHS()));
03240 else return iffMP(eIffEqn, normalize(eIffEqn.getExpr()));
03241 }
03242
03243
03244 Theorem TheoryArithOld::rewrite(const Expr& e)
03245 {
03246 DebugAssert(leavesAreSimp(e), "Expected leaves to be simplified");
03247 TRACE("arith", "TheoryArithOld::rewrite(", e, ") {");
03248 Theorem thm;
03249 if (!e.isTerm()) {
03250 if (!e.isAbsLiteral()) {
03251 if (e.isPropAtom() && leavesAreNumConst(e)) {
03252 if (e.getSize() < 200) {
03253 Expr eNew = e;
03254 thm = reflexivityRule(eNew);
03255 while (eNew.containsTermITE()) {
03256 thm = transitivityRule(thm, getCommonRules()->liftOneITE(eNew));
03257 DebugAssert(!thm.isRefl(), "Expected non-reflexive");
03258 thm = transitivityRule(thm, theoryCore()->getCoreRules()->rewriteIteCond(thm.getRHS()));
03259 thm = transitivityRule(thm, simplify(thm.getRHS()));
03260 eNew = thm.getRHS();
03261 }
03262 }
03263 else {
03264 thm = d_rules->rewriteLeavesConst(e);
03265 if (thm.isRefl()) {
03266 e.setRewriteNormal();
03267 }
03268 else {
03269 thm = transitivityRule(thm, simplify(thm.getRHS()));
03270 }
03271 }
03272
03273
03274
03275
03276 }
03277 else {
03278 e.setRewriteNormal();
03279 thm = reflexivityRule(e);
03280 }
03281 TRACE("arith", "TheoryArithOld::rewrite[non-literal] => ", thm, " }");
03282 return thm;
03283 }
03284 switch(e.getKind()) {
03285 case EQ:
03286 {
03287
03288
03289 if (isLeaf(e[0]) && isLeaf(e[1]))
03290 thm = reflexivityRule(e);
03291 else {
03292
03293 if((e[0].isRational() && e[0].getRational() == 0)
03294 || (e[1].isRational() && e[1].getRational() == 0))
03295
03296 thm = reflexivityRule(e);
03297 else {
03298 thm = d_rules->rightMinusLeft(e);
03299 thm = canonPredEquiv(thm);
03300 }
03301
03302 if ((thm.getRHS())[0].isRational() && (thm.getRHS())[1].isRational()) {
03303 thm = transitivityRule(thm, d_rules->constPredicate(thm.getRHS()));
03304 } else {
03305
03306 thm = normalize(thm);
03307
03308 if (!thm.getRHS().isBoolConst())
03309 thm = canonPredEquiv(thm);
03310 }
03311 }
03312
03313
03314
03315 const Expr& eq = thm.getRHS();
03316 if(eq.isEq() && eq[0] < eq[1])
03317 thm = transitivityRule(thm, getCommonRules()->rewriteUsingSymmetry(eq));
03318
03319
03320 Expr nonlinearEq = thm.getRHS();
03321 if (nonlinearEq.isEq() && isNonlinearEq(nonlinearEq)) {
03322
03323 TRACE("arith nonlinear", "nonlinear eq rewrite: ", nonlinearEq, "");
03324
03325 Expr left = nonlinearEq[0];
03326 Expr right = nonlinearEq[1];
03327
03328
03329 if (isNonlinearSumTerm(left) && right.isRational() && right.getRational() == 0) {
03330 Theorem eq_thm = d_rules->multEqZero(nonlinearEq);
03331 thm = transitivityRule(thm, eq_thm);
03332 thm = transitivityRule(thm, theoryCore()->simplify(thm.getRHS()));
03333 break;
03334 }
03335
03336
03337 if (isPlus(left)) {
03338
03339
03340 if (left[0].getRational() == 0) {
03341 Expr::iterator i = left.begin(), iend = left.end();
03342 ++ i;
03343 set<Expr> factors;
03344 set<Expr>::iterator is, isend;
03345 getFactors(*i, factors);
03346 for (++i; i != iend; ++i) {
03347 set<Expr> factors2;
03348 getFactors(*i, factors2);
03349 for (is = factors.begin(), isend = factors.end(); is != isend;) {
03350 if (factors2.find(*is) == factors2.end()) {
03351 factors.erase(is ++);
03352 } else
03353 ++ is;
03354 }
03355 if (factors.empty()) break;
03356 }
03357 if (!factors.empty()) {
03358 thm = transitivityRule(thm, d_rules->divideEqnNonConst(left, rat(0), *(factors.begin())));
03359
03360 thm = transitivityRule(thm, simplify(thm.getRHS()));
03361 TRACE("arith nonlinear", "nonlinear eq rewrite (factoring): ", thm.getRHS(), "");
03362 break;
03363 }
03364 }
03365
03366
03367 Rational constant;
03368 Expr power1;
03369 Expr power2;
03370 if (isPowersEquality(nonlinearEq, power1, power2)) {
03371
03372 thm = transitivityRule(thm, d_rules->elimPower(nonlinearEq));
03373 thm = transitivityRule(thm, simplify(thm.getRHS()));
03374 TRACE("arith nonlinear", "nonlinear eq rewrite (equal powers): ", thm.getRHS(), "");
03375 break;
03376 } else
03377
03378 if (isPowerEquality(nonlinearEq, constant, power1)) {
03379 Rational pow1 = power1[0].getRational();
03380 if (pow1 % 2 == 0 && constant < 0) {
03381 thm = transitivityRule(thm, d_rules->evenPowerEqNegConst(nonlinearEq));
03382 TRACE("arith nonlinear", "nonlinear eq rewrite (even power = negative): ", thm.getRHS(), "");
03383 break;
03384 }
03385 DebugAssert(constant != 0, "Expected nonzero const");
03386 Rational root = ratRoot(constant, pow1.getUnsigned());
03387 if (root != 0) {
03388 thm = transitivityRule(thm, d_rules->elimPowerConst(nonlinearEq, root));
03389 thm = transitivityRule(thm, simplify(thm.getRHS()));
03390 TRACE("arith nonlinear", "nonlinear eq rewrite (rational root): ", thm.getRHS(), "");
03391 break;
03392 } else {
03393 Theorem isIntPower(isIntegerThm(left));
03394 if (!isIntPower.isNull()) {
03395 thm = transitivityRule(thm, d_rules->intEqIrrational(nonlinearEq, isIntPower));
03396 TRACE("arith nonlinear", "nonlinear eq rewrite (irational root): ", thm.getRHS(), "");
03397 break;
03398 }
03399 }
03400 }
03401 }
03402
03403
03404 if (!canPickEqMonomial(nonlinearEq[0])) {
03405 thm = transitivityRule(thm, d_rules->eqToIneq(nonlinearEq));
03406 thm = transitivityRule(thm, simplify(thm.getRHS()));
03407 TRACE("arith nonlinear", "nonlinear eq rewrite (not solvable): ", thm.getRHS(), "");
03408 break;
03409 }
03410 }
03411 }
03412 break;
03413 case GRAY_SHADOW:
03414 case DARK_SHADOW:
03415 thm = reflexivityRule(e);
03416 break;
03417 case IS_INTEGER: {
03418 Theorem res(isIntegerDerive(e, typePred(e[0])));
03419 if(!res.isNull())
03420 thm = getCommonRules()->iffTrue(res);
03421 else
03422 thm = reflexivityRule(e);
03423 break;
03424 }
03425 case NOT:
03426 if (!isIneq(e[0]))
03427
03428 thm = reflexivityRule(e);
03429 else {
03430
03431
03432 thm = d_rules->negatedInequality(e);
03433 DebugAssert(isGE(thm.getRHS()) || isGT(thm.getRHS()),
03434 "Expected GE or GT");
03435 thm = transitivityRule(thm, d_rules->flipInequality(thm.getRHS()));
03436 thm = transitivityRule(thm, d_rules->rightMinusLeft(thm.getRHS()));
03437 thm = canonPredEquiv(thm);
03438
03439
03440 Expr theIneq = thm.getRHS();
03441 if(isLT(theIneq)) {
03442
03443 Theorem isIntLHS(isIntegerThm(theIneq[0]));
03444 Theorem isIntRHS(isIntegerThm(theIneq[1]));
03445 bool isInt = (!isIntLHS.isNull() && !isIntRHS.isNull());
03446 if (isInt) {
03447 thm = canonPredEquiv(
03448 transitivityRule(thm, d_rules->lessThanToLERewrite(theIneq, isIntLHS, isIntRHS, true)));
03449 }
03450 }
03451
03452
03453 if ((thm.getRHS())[1].isRational())
03454 thm = transitivityRule(thm, d_rules->constPredicate(thm.getRHS()));
03455 else {
03456
03457 thm = normalize(thm);
03458
03459 thm = canonPredEquiv(thm);
03460 }
03461 }
03462 break;
03463 case LT:
03464 case GT:
03465 case LE:
03466 case GE: {
03467
03468 if (isGE(e) || isGT(e)) {
03469 thm = d_rules->flipInequality(e);
03470 thm = transitivityRule(thm, d_rules->rightMinusLeft(thm.getRHS()));
03471 }
03472 else
03473 thm = d_rules->rightMinusLeft(e);
03474
03475 thm = canonPredEquiv(thm);
03476
03477
03478 Expr theIneq = thm.getRHS();
03479 if(isLT(theIneq)) {
03480
03481 Theorem isIntLHS(isIntegerThm(theIneq[0]));
03482 Theorem isIntRHS(isIntegerThm(theIneq[1]));
03483 bool isInt = (!isIntLHS.isNull() && !isIntRHS.isNull());
03484 if (isInt) {
03485 thm = canonPredEquiv(
03486 transitivityRule(thm, d_rules->lessThanToLERewrite(theIneq, isIntLHS, isIntRHS, true)));
03487 }
03488 }
03489
03490
03491 if ((thm.getRHS())[1].isRational())
03492 thm = transitivityRule(thm, d_rules->constPredicate(thm.getRHS()));
03493 else {
03494 thm = normalize(thm);
03495 thm = canonPredEquiv(thm);
03496 if (thm.getRHS()[1].isRational())
03497 thm = transitivityRule(thm, d_rules->constPredicate(thm.getRHS()));
03498 }
03499 break;
03500 }
03501 default:
03502 DebugAssert(false,
03503 "Theory_Arith::rewrite: control should not reach here");
03504 break;
03505 }
03506 }
03507 else {
03508 if (e.isAtomic())
03509 thm = canon(e);
03510 else
03511 thm = reflexivityRule(e);
03512 }
03513
03514
03515 if (theoryOf(thm.getRHS()) == this)
03516 thm.getRHS().setRewriteNormal();
03517 TRACE("arith", "TheoryArithOld::rewrite => ", thm, " }");
03518 return thm;
03519 }
03520
03521
03522 void TheoryArithOld::setup(const Expr& e)
03523 {
03524 if (!e.isTerm()) {
03525 if (e.isNot()) return;
03526
03527
03528
03529
03530 if (isIneq(e)) {
03531 DebugAssert((isLT(e)||isLE(e)) &&
03532 e[0].isRational() && e[0].getRational() == 0,
03533 "TheoryArithOld::setup: expected 0 < rhs:" + e.toString());
03534 e[1].addToNotify(this, e);
03535 } else {
03536
03537
03538
03539
03540
03541
03542
03543
03544
03545
03546 }
03547 return;
03548 }
03549 int k(0), ar(e.arity());
03550 for ( ; k < ar; ++k) {
03551 e[k].addToNotify(this, e);
03552 TRACE("arith setup", "e["+int2string(k)+"]: ", *(e[k].getNotify()), "");
03553 }
03554 }
03555
03556
03557 void TheoryArithOld::update(const Theorem& e, const Expr& d)
03558 {
03559 TRACE("arith update", "update on " + d.toString() + " with ", e.getRHS().toString(), ".");
03560
03561 if (inconsistent()) return;
03562
03563
03564 DebugAssert(d.hasFind() || isIneq(d), "update on a non-inequality term/atom");
03565
03566 IF_DEBUG(debugger.counter("arith update total")++;)
03567
03568
03569
03570
03571
03572
03573
03574
03575
03576
03577
03578
03579
03580
03581
03582
03583
03584
03585
03586
03587
03588
03589
03590 if (isIneq(d)) {
03591
03592
03593 DebugAssert(e.getLHS() == d[1], "Mismatch");
03594 Theorem thm;
03595 if (d.hasFind()) thm = find(d);
03596
03597
03598
03599
03600
03601
03602
03603
03604
03605
03606
03607
03608
03609
03610
03611
03612
03613
03614
03615
03616
03617
03618
03619
03620
03621
03622
03623
03624
03625
03626
03627
03628
03629 vector<unsigned> changed;
03630 vector<Theorem> children;
03631 changed.push_back(1);
03632 children.push_back(e);
03633 Theorem thm2 = substitutivityRule(d, changed, children);
03634 Expr newIneq = thm2.getRHS();
03635
03636
03637
03638
03639
03640 if ((thm.isNull() || thm.getRHS() != falseExpr()) &&
03641 bufferedInequalities.find(d) != bufferedInequalities.end() &&
03642 alreadyProjected.find(d) == alreadyProjected.end()) {
03643 TRACE("arith update", "simplified but not projected : ", thm2.getRHS(), "");
03644 dontBuffer[thm2.getRHS()] = true;
03645 }
03646
03647 if (thm.isNull()) {
03648
03649
03650
03651 TRACE("arith update", "in udpate, but no find", "", "");
03652 if (bufferedInequalities.find(d) != bufferedInequalities.end()) {
03653 if (thm2.getRHS()[1].isRational()) enqueueFact(iffMP(bufferedInequalities[d], thm2));
03654 else if (alreadyProjected.find(d) != alreadyProjected.end()) {
03655
03656 alreadyProjected[d] = d;
03657 }
03658 }
03659 }
03660 else if (thm.getRHS() == trueExpr()) {
03661 if (!newIneq[1].isRational() || newIneq[1].getRational() <= 0)
03662 enqueueFact(iffMP(getCommonRules()->iffTrueElim(thm), thm2));
03663 }
03664 else {
03665 enqueueFact(getCommonRules()->iffFalseElim(
03666 transitivityRule(symmetryRule(thm2), thm)));
03667 }
03668 IF_DEBUG(debugger.counter("arith update ineq")++;)
03669 }
03670 else if (d.isEq()) {
03671 TRACE("arith nonlinear", "TheoryArithOld::update() on equality ", d, "");
03672
03673
03674 vector<unsigned> changed;
03675 vector<Theorem> children;
03676 changed.push_back(0);
03677 children.push_back(e);
03678 Theorem thm = substitutivityRule(d, changed, children);
03679 Expr newEq = thm.getRHS();
03680
03681 Theorem d_find = find(d);
03682 if (d_find.getRHS() == trueExpr()) enqueueFact(iffMP(getCommonRules()->iffTrueElim(d_find), thm));
03683 else enqueueFact(getCommonRules()->iffFalseElim(transitivityRule(symmetryRule(thm), d_find)));
03684 }
03685 else if (d.getKind() == IS_INTEGER) {
03686
03687 DebugAssert(e.getRHS() == findExpr(d[0]), "Unexpected");
03688 if (isInteger(e.getRHS())) {
03689 Theorem thm = substitutivityRule(d, find(d[0]));
03690 thm = transitivityRule(symmetryRule(find(d)), thm);
03691 thm = iffMP(thm, simplify(thm.getExpr()));
03692 setInconsistent(thm);
03693 }
03694 else {
03695 e.getRHS().addToNotify(this, d);
03696 }
03697 }
03698 else if (find(d).getRHS() == d) {
03699
03700
03701
03702
03703
03704
03705 Theorem thm = simplify(d);
03706
03707 if (d_sharedTerms.find(d) != d_sharedTerms.end()) addSharedTerm(thm.getRHS());
03708 DebugAssert(thm.getRHS().isAtomic(), "Expected atomic");
03709 assertEqualities(thm);
03710 }
03711 }
03712
03713
03714 Theorem TheoryArithOld::solve(const Theorem& thm)
03715 {
03716 DebugAssert(thm.isRewrite() && thm.getLHS().isTerm(), "");
03717 const Expr& lhs = thm.getLHS();
03718 const Expr& rhs = thm.getRHS();
03719
03720
03721
03722
03723
03724
03725 if (isLeaf(lhs) && !isLeafIn(lhs, rhs)
03726 && (!isInteger(lhs) || isInteger(rhs))
03727
03728 )
03729 return thm;
03730
03731
03732 if (isLeaf(rhs) && !isLeafIn(rhs, lhs)
03733 && (!isInteger(rhs) || isInteger(lhs))
03734
03735 )
03736 return symmetryRule(thm);
03737
03738 return doSolve(thm);
03739 }
03740
03741
03742 void TheoryArithOld::computeModelTerm(const Expr& e, std::vector<Expr>& v) {
03743 switch(e.getKind()) {
03744 case RATIONAL_EXPR:
03745 break;
03746 case PLUS:
03747 case MULT:
03748 case DIVIDE:
03749 case POW:
03750 for(Expr::iterator i=e.begin(), iend=e.end(); i!=iend; ++i)
03751
03752 v.push_back(*i);
03753 break;
03754 default: {
03755 Expr e2(findExpr(e));
03756 if(e==e2) {
03757 TRACE("model", "TheoryArithOld::computeModelTerm(", e, "): a variable");
03758
03759
03760 } else {
03761 TRACE("model", "TheoryArithOld::computeModelTerm("+e.toString()
03762 +"): has find pointer to ", e2, "");
03763 v.push_back(e2);
03764 }
03765 }
03766 }
03767 }
03768
03769
03770 Expr TheoryArithOld::computeTypePred(const Type& t, const Expr& e) {
03771 Expr tExpr = t.getExpr();
03772 switch(tExpr.getKind()) {
03773 case INT:
03774 return Expr(IS_INTEGER, e);
03775 case SUBRANGE: {
03776 std::vector<Expr> kids;
03777 kids.push_back(Expr(IS_INTEGER, e));
03778 kids.push_back(leExpr(tExpr[0], e));
03779 kids.push_back(leExpr(e, tExpr[1]));
03780 return andExpr(kids);
03781 }
03782 default:
03783 return e.getEM()->trueExpr();
03784 }
03785 }
03786
03787
03788 void TheoryArithOld::checkAssertEqInvariant(const Theorem& e)
03789 {
03790 if (e.isRewrite()) {
03791 DebugAssert(e.getLHS().isTerm(), "Expected equation");
03792 if (isLeaf(e.getLHS())) {
03793
03794 DebugAssert(!isLeafIn(e.getLHS(),e.getRHS()),
03795 "Not in solved form: lhs appears in rhs");
03796 }
03797 else {
03798 DebugAssert(e.getLHS().hasFind(), "Expected lhs to have find");
03799 DebugAssert(!leavesAreSimp(e.getLHS()),
03800 "Expected at least one unsimplified leaf on lhs");
03801 }
03802 DebugAssert(canonSimp(e.getRHS()).getRHS() == e.getRHS(),
03803 "Expected canonSimp(rhs) = canonSimp(rhs)");
03804 }
03805 else {
03806 Expr expr = e.getExpr();
03807 if (expr.isFalse()) return;
03808
03809 vector<Theorem> eqs;
03810 Theorem thm;
03811 int index, index2;
03812
03813 for (index = 0; index < expr.arity(); ++index) {
03814 thm = getCommonRules()->andElim(e, index);
03815 eqs.push_back(thm);
03816 if (thm.getExpr().isFalse()) return;
03817 DebugAssert(eqs[index].isRewrite() &&
03818 eqs[index].getLHS().isTerm(), "Expected equation");
03819 }
03820
03821
03822 for (index = 0; index < expr.arity(); ++index) {
03823 DebugAssert(isLeaf(eqs[index].getLHS()), "expected leaf on lhs");
03824 DebugAssert(canonSimp(eqs[index].getRHS()).getRHS() == eqs[index].getRHS(),
03825 "Expected canonSimp(rhs) = canonSimp(rhs)");
03826 DebugAssert(recursiveCanonSimpCheck(eqs[index].getRHS()),
03827 "Failed recursive canonSimp check");
03828 for (index2 = 0; index2 < expr.arity(); ++index2) {
03829 DebugAssert(index == index2 ||
03830 eqs[index].getLHS() != eqs[index2].getLHS(),
03831 "Not in solved form: repeated lhs");
03832 DebugAssert(!isLeafIn(eqs[index].getLHS(),eqs[index2].getRHS()),
03833 "Not in solved form: lhs appears in rhs");
03834 }
03835 }
03836 }
03837 }
03838
03839
03840 void TheoryArithOld::checkType(const Expr& e)
03841 {
03842 switch (e.getKind()) {
03843 case INT:
03844 case REAL:
03845 if (e.arity() > 0) {
03846 throw Exception("Ill-formed arithmetic type: "+e.toString());
03847 }
03848 break;
03849 case SUBRANGE:
03850 if (e.arity() != 2 ||
03851 !isIntegerConst(e[0]) ||
03852 !isIntegerConst(e[1]) ||
03853 e[0].getRational() > e[1].getRational()) {
03854 throw Exception("bad SUBRANGE type expression"+e.toString());
03855 }
03856 break;
03857 default:
03858 DebugAssert(false, "Unexpected kind in TheoryArithOld::checkType"
03859 +getEM()->getKindName(e.getKind()));
03860 }
03861 }
03862
03863
03864 Cardinality TheoryArithOld::finiteTypeInfo(Expr& e, Unsigned& n,
03865 bool enumerate, bool computeSize)
03866 {
03867 Cardinality card = CARD_INFINITE;
03868 switch (e.getKind()) {
03869 case SUBRANGE: {
03870 card = CARD_FINITE;
03871 Expr typeExpr = e;
03872 if (enumerate) {
03873 Rational r = typeExpr[0].getRational() + n;
03874 if (r <= typeExpr[1].getRational()) {
03875 e = rat(r);
03876 }
03877 else e = Expr();
03878 }
03879 if (computeSize) {
03880 Rational r = typeExpr[1].getRational() - typeExpr[0].getRational() + 1;
03881 n = r.getUnsigned();
03882 }
03883 break;
03884 }
03885 default:
03886 break;
03887 }
03888 return card;
03889 }
03890
03891
03892 void TheoryArithOld::computeType(const Expr& e)
03893 {
03894 switch (e.getKind()) {
03895 case REAL_CONST:
03896 e.setType(d_realType);
03897 break;
03898 case RATIONAL_EXPR:
03899 if(e.getRational().isInteger())
03900 e.setType(d_intType);
03901 else
03902 e.setType(d_realType);
03903 break;
03904 case UMINUS:
03905 case PLUS:
03906 case MINUS:
03907 case MULT:
03908 case POW: {
03909 bool isInt = true;
03910 for(int k = 0; k < e.arity(); ++k) {
03911 if(d_realType != getBaseType(e[k]))
03912 throw TypecheckException("Expecting type REAL with `" +
03913 getEM()->getKindName(e.getKind()) + "',\n"+
03914 "but got a " + getBaseType(e[k]).toString()+
03915 " for:\n" + e.toString());
03916 if(isInt && !isInteger(e[k]))
03917 isInt = false;
03918 }
03919 if(isInt)
03920 e.setType(d_intType);
03921 else
03922 e.setType(d_realType);
03923 break;
03924 }
03925 case DIVIDE: {
03926 Expr numerator = e[0];
03927 Expr denominator = e[1];
03928 if (getBaseType(numerator) != d_realType ||
03929 getBaseType(denominator) != d_realType) {
03930 throw TypecheckException("Expecting only REAL types with `DIVIDE',\n"
03931 "but got " + getBaseType(numerator).toString()+
03932 " and " + getBaseType(denominator).toString() +
03933 " for:\n" + e.toString());
03934 }
03935 if(denominator.isRational() && 1 == denominator.getRational())
03936 e.setType(numerator.getType());
03937 else
03938 e.setType(d_realType);
03939 break;
03940 }
03941 case LT:
03942 case LE:
03943 case GT:
03944 case GE:
03945 case GRAY_SHADOW:
03946
03947
03948
03949 case DARK_SHADOW:
03950 for (int k = 0; k < e.arity(); ++k) {
03951 if (d_realType != getBaseType(e[k]))
03952 throw TypecheckException("Expecting type REAL with `" +
03953 getEM()->getKindName(e.getKind()) + "',\n"+
03954 "but got a " + getBaseType(e[k]).toString()+
03955 " for:\n" + e.toString());
03956 }
03957
03958 e.setType(boolType());
03959 break;
03960 case IS_INTEGER:
03961 if(d_realType != getBaseType(e[0]))
03962 throw TypecheckException("Expected type REAL, but got "
03963 +getBaseType(e[0]).toString()
03964 +"\n\nExpr = "+e.toString());
03965 e.setType(boolType());
03966 break;
03967 default:
03968 DebugAssert(false,"TheoryArithOld::computeType: unexpected expression:\n "
03969 +e.toString());
03970 break;
03971 }
03972 }
03973
03974
03975 Type TheoryArithOld::computeBaseType(const Type& t) {
03976 IF_DEBUG(int kind = t.getExpr().getKind();)
03977 DebugAssert(kind==INT || kind==REAL || kind==SUBRANGE,
03978 "TheoryArithOld::computeBaseType("+t.toString()+")");
03979 return realType();
03980 }
03981
03982
03983 Expr
03984 TheoryArithOld::computeTCC(const Expr& e) {
03985 Expr tcc(Theory::computeTCC(e));
03986 switch(e.getKind()) {
03987 case DIVIDE:
03988 DebugAssert(e.arity() == 2, "");
03989 return tcc.andExpr(!(e[1].eqExpr(rat(0))));
03990 default:
03991 return tcc;
03992 }
03993 }
03994
03995
03996
03997
03998
03999 Expr
04000 TheoryArithOld::parseExprOp(const Expr& e) {
04001 TRACE("parser", "TheoryArithOld::parseExprOp(", e, ")");
04002
04003
04004
04005 switch(e.getKind()) {
04006 case ID: {
04007 int kind = getEM()->getKind(e[0].getString());
04008 switch(kind) {
04009 case NULL_KIND: return e;
04010 case REAL:
04011 case INT:
04012 case NEGINF:
04013 case POSINF: return getEM()->newLeafExpr(kind);
04014 default:
04015 DebugAssert(false, "Bad use of bare keyword: "+e.toString());
04016 return e;
04017 }
04018 }
04019 case RAW_LIST: break;
04020 default:
04021 return e;
04022 }
04023
04024 DebugAssert(e.getKind() == RAW_LIST && e.arity() > 0,
04025 "TheoryArithOld::parseExprOp:\n e = "+e.toString());
04026
04027 const Expr& c1 = e[0][0];
04028 int kind = getEM()->getKind(c1.getString());
04029 switch(kind) {
04030 case UMINUS: {
04031 if(e.arity() != 2)
04032 throw ParserException("UMINUS requires exactly one argument: "
04033 +e.toString());
04034 return uminusExpr(parseExpr(e[1]));
04035 }
04036 case PLUS: {
04037 vector<Expr> k;
04038 Expr::iterator i = e.begin(), iend=e.end();
04039
04040
04041 ++i;
04042
04043 for(; i!=iend; ++i) k.push_back(parseExpr(*i));
04044 return plusExpr(k);
04045 }
04046 case MINUS: {
04047 if(e.arity() == 2) {
04048 if (false && getEM()->getInputLang() == SMTLIB_LANG) {
04049 throw ParserException("Unary Minus should use '~' instead of '-' in SMT-LIB expr:"
04050 +e.toString());
04051 }
04052 else {
04053 return uminusExpr(parseExpr(e[1]));
04054 }
04055 }
04056 else if(e.arity() == 3)
04057 return minusExpr(parseExpr(e[1]), parseExpr(e[2]));
04058 else
04059 throw ParserException("MINUS requires one or two arguments:"
04060 +e.toString());
04061 }
04062 case MULT: {
04063 vector<Expr> k;
04064 Expr::iterator i = e.begin(), iend=e.end();
04065
04066
04067 ++i;
04068
04069 for(; i!=iend; ++i) k.push_back(parseExpr(*i));
04070 return multExpr(k);
04071 }
04072 case POW: {
04073 return powExpr(parseExpr(e[1]), parseExpr(e[2]));
04074 }
04075 case DIVIDE:
04076 { return divideExpr(parseExpr(e[1]), parseExpr(e[2])); }
04077 case LT:
04078 { return ltExpr(parseExpr(e[1]), parseExpr(e[2])); }
04079 case LE:
04080 { return leExpr(parseExpr(e[1]), parseExpr(e[2])); }
04081 case GT:
04082 { return gtExpr(parseExpr(e[1]), parseExpr(e[2])); }
04083 case GE:
04084 { return geExpr(parseExpr(e[1]), parseExpr(e[2])); }
04085 case INTDIV:
04086 case MOD:
04087 case SUBRANGE: {
04088 vector<Expr> k;
04089 Expr::iterator i = e.begin(), iend=e.end();
04090
04091
04092 ++i;
04093
04094 for(; i!=iend; ++i)
04095 k.push_back(parseExpr(*i));
04096 return Expr(kind, k, e.getEM());
04097 }
04098 case IS_INTEGER: {
04099 if(e.arity() != 2)
04100 throw ParserException("IS_INTEGER requires exactly one argument: "
04101 +e.toString());
04102 return Expr(IS_INTEGER, parseExpr(e[1]));
04103 }
04104 default:
04105 DebugAssert(false,
04106 "TheoryArithOld::parseExprOp: invalid input " + e.toString());
04107 break;
04108 }
04109 return e;
04110 }
04111
04112
04113
04114
04115
04116
04117 ExprStream&
04118 TheoryArithOld::print(ExprStream& os, const Expr& e) {
04119 switch(os.lang()) {
04120 case SIMPLIFY_LANG:
04121 switch(e.getKind()) {
04122 case RATIONAL_EXPR:
04123 e.print(os);
04124 break;
04125 case SUBRANGE:
04126 os <<"ERROR:SUBRANGE:not supported in Simplify\n";
04127 break;
04128 case IS_INTEGER:
04129 os <<"ERROR:IS_INTEGER:not supported in Simplify\n";
04130 break;
04131 case PLUS: {
04132 int i=0, iend=e.arity();
04133 os << "(+ ";
04134 if(i!=iend) os << e[i];
04135 ++i;
04136 for(; i!=iend; ++i) os << " " << e[i];
04137 os << ")";
04138 break;
04139 }
04140 case MINUS:
04141 os << "(- " << e[0] << " " << e[1]<< ")";
04142 break;
04143 case UMINUS:
04144 os << "-" << e[0] ;
04145 break;
04146 case MULT: {
04147 int i=0, iend=e.arity();
04148 os << "(* " ;
04149 if(i!=iend) os << e[i];
04150 ++i;
04151 for(; i!=iend; ++i) os << " " << e[i];
04152 os << ")";
04153 break;
04154 }
04155 case POW:
04156 os << "(" << push << e[1] << space << "^ " << e[0] << push << ")";
04157 break;
04158 case DIVIDE:
04159 os << "(" << push << e[0] << space << "/ " << e[1] << push << ")";
04160 break;
04161 case LT:
04162 if (isInt(e[0].getType()) || isInt(e[1].getType())) {
04163 }
04164 os << "(< " << e[0] << " " << e[1] <<")";
04165 break;
04166 case LE:
04167 os << "(<= " << e[0] << " " << e[1] << ")";
04168 break;
04169 case GT:
04170 os << "(> " << e[0] << " " << e[1] << ")";
04171 break;
04172 case GE:
04173 os << "(>= " << e[0] << " " << e[1] << ")";
04174 break;
04175 case DARK_SHADOW:
04176 case GRAY_SHADOW:
04177 os <<"ERROR:SHADOW:not supported in Simplify\n";
04178 break;
04179 default:
04180
04181
04182 e.print(os);
04183
04184 break;
04185 }
04186 break;
04187
04188 case TPTP_LANG:
04189 switch(e.getKind()) {
04190 case RATIONAL_EXPR:
04191 e.print(os);
04192 break;
04193 case SUBRANGE:
04194 os <<"ERROR:SUBRANGE:not supported in TPTP\n";
04195 break;
04196 case IS_INTEGER:
04197 os <<"ERROR:IS_INTEGER:not supported in TPTP\n";
04198 break;
04199 case PLUS: {
04200 if(!isInteger(e[0])){
04201 os<<"ERRPR:plus only supports inteters now in TPTP\n";
04202 break;
04203 }
04204
04205 int i=0, iend=e.arity();
04206 if(iend <=1){
04207 os<<"ERROR,plus must have more than two numbers in TPTP\n";
04208 break;
04209 }
04210
04211 for(i=0; i <= iend-2; ++i){
04212 os << "$plus_int(";
04213 os << e[i] << ",";
04214 }
04215
04216 os<< e[iend-1];
04217
04218 for(i=0 ; i <= iend-2; ++i){
04219 os << ")";
04220 }
04221
04222 break;
04223 }
04224 case MINUS:
04225 if(!isInteger(e[0])){
04226 os<<"ERRPR:arithmetic operations only support inteters now in TPTP\n";
04227 break;
04228 }
04229
04230 os << "$minus_int(" << e[0] << "," << e[1]<< ")";
04231 break;
04232 case UMINUS:
04233 if(!isInteger(e[0])){
04234 os<<"ERRPR:arithmetic operations only support inteters now in TPTP\n";
04235 break;
04236 }
04237
04238 os << "$uminus_int(" << e[0] <<")" ;
04239 break;
04240 case MULT: {
04241 if(!isInteger(e[0])){
04242 os<<"ERRPR:times only supports inteters now in TPTP\n";
04243 break;
04244 }
04245
04246 int i=0, iend=e.arity();
04247 if(iend <=1){
04248 os<<"ERROR:times must have more than two numbers in TPTP\n";
04249 break;
04250 }
04251
04252 for(i=0; i <= iend-2; ++i){
04253 os << "$times_int(";
04254 os << e[i] << ",";
04255 }
04256
04257 os<< e[iend-1];
04258
04259 for(i=0 ; i <= iend-2; ++i){
04260 os << ")";
04261 }
04262
04263 break;
04264 }
04265 case POW:
04266
04267 if(!isInteger(e[0])){
04268 os<<"ERRPR:arithmetic operations only support inteters now in TPTP\n";
04269 break;
04270 }
04271
04272 os << "$power_int(" << push << e[1] << space << "^ " << e[0] << push << ")";
04273 break;
04274
04275 case DIVIDE:
04276 if(!isInteger(e[0])){
04277 os<<"ERRPR:arithmetic operations only support inteters now in TPTP\n";
04278 break;
04279 }
04280
04281 os << "divide_int(" <<e[0] << "," << e[1] << ")";
04282 break;
04283
04284 case LT:
04285 if(!isInteger(e[0])){
04286 os<<"ERRPR:arithmetic operations only support inteters now in TPTP\n";
04287 break;
04288 }
04289 os << "$less_int(" << e[0] << "," << e[1] <<")";
04290 break;
04291
04292 case LE:
04293 if(!isInteger(e[0])){
04294 os<<"ERRPR:arithmetic operations only support inteters now in TPTP\n";
04295 break;
04296 }
04297
04298 os << "$lesseq_int(" << e[0] << "," << e[1] << ")";
04299 break;
04300
04301 case GT:
04302 if(!isInteger(e[0])){
04303 os<<"ERRPR:arithmetic operations only support inteters now in TPTP\n";
04304 break;
04305 }
04306
04307 os << "$greater_int(" << e[0] << "," << e[1] << ")";
04308 break;
04309
04310 case GE:
04311 if(!isInteger(e[0])){
04312 os<<"ERRPR:arithmetic operations only support inteters now in TPTP\n";
04313 break;
04314 }
04315
04316 os << "$greatereq_int(" << e[0] << "," << e[1] << ")";
04317 break;
04318 case DARK_SHADOW:
04319 case GRAY_SHADOW:
04320 os <<"ERROR:SHADOW:not supported in TPTP\n";
04321 break;
04322
04323 case INT:
04324 os <<"$int";
04325 break;
04326 case REAL:
04327 os <<"ERROR:REAL not supported in TPTP\n";
04328 default:
04329
04330
04331 e.print(os);
04332
04333 break;
04334 }
04335 break;
04336
04337 case PRESENTATION_LANG:
04338 switch(e.getKind()) {
04339 case REAL:
04340 os << "REAL";
04341 break;
04342 case INT:
04343 os << "INT";
04344 break;
04345 case RATIONAL_EXPR:
04346 e.print(os);
04347 break;
04348 case NEGINF:
04349 os << "NEGINF";
04350 break;
04351 case POSINF:
04352 os << "POSINF";
04353 break;
04354 case SUBRANGE:
04355 if(e.arity() != 2) e.printAST(os);
04356 else
04357 os << "[" << push << e[0] << ".." << e[1] << push << "]";
04358 break;
04359 case IS_INTEGER:
04360 if(e.arity() == 1)
04361 os << "IS_INTEGER(" << push << e[0] << push << ")";
04362 else
04363 e.printAST(os);
04364 break;
04365 case PLUS: {
04366 int i=0, iend=e.arity();
04367 os << "(" << push;
04368 if(i!=iend) os << e[i];
04369 ++i;
04370 for(; i!=iend; ++i) os << space << "+ " << e[i];
04371 os << push << ")";
04372 break;
04373 }
04374 case MINUS:
04375 os << "(" << push << e[0] << space << "- " << e[1] << push << ")";
04376 break;
04377 case UMINUS:
04378 os << "-(" << push << e[0] << push << ")";
04379 break;
04380 case MULT: {
04381 int i=0, iend=e.arity();
04382 os << "(" << push;
04383 if(i!=iend) os << e[i];
04384 ++i;
04385 for(; i!=iend; ++i) os << space << "* " << e[i];
04386 os << push << ")";
04387 break;
04388 }
04389 case POW:
04390 os << "(" << push << e[1] << space << "^ " << e[0] << push << ")";
04391 break;
04392 case DIVIDE:
04393 os << "(" << push << e[0] << space << "/ " << e[1] << push << ")";
04394 break;
04395 case LT:
04396 if (isInt(e[0].getType()) || isInt(e[1].getType())) {
04397 }
04398 os << "(" << push << e[0] << space << "< " << e[1] << push << ")";
04399 break;
04400 case LE:
04401 os << "(" << push << e[0] << space << "<= " << e[1] << push << ")";
04402 break;
04403 case GT:
04404 os << "(" << push << e[0] << space << "> " << e[1] << push << ")";
04405 break;
04406 case GE:
04407 os << "(" << push << e[0] << space << ">= " << e[1] << push << ")";
04408 break;
04409 case DARK_SHADOW:
04410 os << "DARK_SHADOW(" << push << e[0] << ", " << space << e[1] << push << ")";
04411 break;
04412 case GRAY_SHADOW:
04413 os << "GRAY_SHADOW(" << push << e[0] << "," << space << e[1]
04414 << "," << space << e[2] << "," << space << e[3] << push << ")";
04415 break;
04416 default:
04417
04418
04419 e.printAST(os);
04420
04421 break;
04422 }
04423 break;
04424 case SMTLIB_LANG: {
04425 switch(e.getKind()) {
04426 case REAL_CONST:
04427 printRational(os, e[0].getRational(), true);
04428 break;
04429 case RATIONAL_EXPR:
04430 printRational(os, e.getRational());
04431 break;
04432 case REAL:
04433 os << "Real";
04434 break;
04435 case INT:
04436 os << "Int";
04437 break;
04438 case SUBRANGE:
04439 throw SmtlibException("TheoryArithOld::print: SMTLIB: SUBRANGE not implemented");
04440
04441
04442
04443
04444 break;
04445 case IS_INTEGER:
04446 if(e.arity() == 1)
04447 os << "(" << push << "IsInt" << space << e[0] << push << ")";
04448 else
04449 throw SmtlibException("TheoryArithOld::print: SMTLIB: IS_INTEGER used unexpectedly");
04450 break;
04451 case PLUS: {
04452 os << "(" << push << "+";
04453 Expr::iterator i = e.begin(), iend = e.end();
04454 for(; i!=iend; ++i) {
04455 os << space << (*i);
04456 }
04457 os << push << ")";
04458 break;
04459 }
04460 case MINUS: {
04461 os << "(" << push << "- " << e[0] << space << e[1] << push << ")";
04462 break;
04463 }
04464 case UMINUS: {
04465 os << "(" << push << "~" << space << e[0] << push << ")";
04466 break;
04467 }
04468 case MULT: {
04469 int i=0, iend=e.arity();
04470 for(; i!=iend; ++i) {
04471 if (i < iend-1) {
04472 os << "(" << push << "*";
04473 }
04474 os << space << e[i];
04475 }
04476 for (i=0; i < iend-1; ++i) os << push << ")";
04477 break;
04478 }
04479 case POW:
04480 if (e[0].isRational() && e[0].getRational().isInteger()) {
04481 int i=0, iend=e[0].getRational().getInt();
04482 for(; i!=iend; ++i) {
04483 if (i < iend-1) {
04484 os << "(" << push << "*";
04485 }
04486 os << space << e[1];
04487 }
04488 for (i=0; i < iend-1; ++i) os << push << ")";
04489 }
04490 else
04491 throw SmtlibException("TheoryArithOld::print: SMTLIB: POW not supported: " + e.toString(PRESENTATION_LANG));
04492
04493 break;
04494 case DIVIDE: {
04495 throw SmtlibException("TheoryArithOld::print: SMTLIB: unexpected use of DIVIDE");
04496 break;
04497 }
04498 case LT: {
04499 Rational r;
04500 os << "(" << push << "<" << space;
04501 os << e[0] << space << e[1] << push << ")";
04502 break;
04503 }
04504 case LE: {
04505 Rational r;
04506 os << "(" << push << "<=" << space;
04507 os << e[0] << space << e[1] << push << ")";
04508 break;
04509 }
04510 case GT: {
04511 Rational r;
04512 os << "(" << push << ">" << space;
04513 os << e[0] << space << e[1] << push << ")";
04514 break;
04515 }
04516 case GE: {
04517 Rational r;
04518 os << "(" << push << ">=" << space;
04519 os << e[0] << space << e[1] << push << ")";
04520 break;
04521 }
04522 case DARK_SHADOW:
04523 throw SmtlibException("TheoryArithOld::print: SMTLIB: DARK_SHADOW not supported");
04524 os << "(" << push << "DARK_SHADOW" << space << e[0]
04525 << space << e[1] << push << ")";
04526 break;
04527 case GRAY_SHADOW:
04528 throw SmtlibException("TheoryArithOld::print: SMTLIB: GRAY_SHADOW not supported");
04529 os << "GRAY_SHADOW(" << push << e[0] << "," << space << e[1]
04530 << "," << space << e[2] << "," << space << e[3] << push << ")";
04531 break;
04532 default:
04533 throw SmtlibException("TheoryArithOld::print: SMTLIB: default not supported");
04534
04535
04536 e.printAST(os);
04537
04538 break;
04539 }
04540 break;
04541 }
04542 case LISP_LANG:
04543 switch(e.getKind()) {
04544 case REAL:
04545 case INT:
04546 case RATIONAL_EXPR:
04547 case NEGINF:
04548 case POSINF:
04549 e.print(os);
04550 break;
04551 case SUBRANGE:
04552 if(e.arity() != 2) e.printAST(os);
04553 else
04554 os << "(" << push << "SUBRANGE" << space << e[0]
04555 << space << e[1] << push << ")";
04556 break;
04557 case IS_INTEGER:
04558 if(e.arity() == 1)
04559 os << "(" << push << "IS_INTEGER" << space << e[0] << push << ")";
04560 else
04561 e.printAST(os);
04562 break;
04563 case PLUS: {
04564 int i=0, iend=e.arity();
04565 os << "(" << push << "+";
04566 for(; i!=iend; ++i) os << space << e[i];
04567 os << push << ")";
04568 break;
04569 }
04570 case MINUS:
04571
04572 os << "(" << push << "- " << e[0] << space << e[1] << push << ")";
04573 break;
04574 case UMINUS:
04575 os << "(" << push << "-" << space << e[0] << push << ")";
04576 break;
04577 case MULT: {
04578 int i=0, iend=e.arity();
04579 os << "(" << push << "*";
04580 for(; i!=iend; ++i) os << space << e[i];
04581 os << push << ")";
04582 break;
04583 }
04584 case POW:
04585 os << "(" << push << "^ " << e[1] << space << e[0] << push << ")";
04586 break;
04587 case DIVIDE:
04588 os << "(" << push << "/ " << e[0] << space << e[1] << push << ")";
04589 break;
04590 case LT:
04591 os << "(" << push << "< " << e[0] << space << e[1] << push << ")";
04592 break;
04593 case LE:
04594 os << "(" << push << "<= " << e[0] << space << e[1] << push << ")";
04595 break;
04596 case GT:
04597 os << "(" << push << "> " << e[1] << space << e[0] << push << ")";
04598 break;
04599 case GE:
04600 os << "(" << push << ">= " << e[0] << space << e[1] << push << ")";
04601 break;
04602 case DARK_SHADOW:
04603 os << "(" << push << "DARK_SHADOW" << space << e[0]
04604 << space << e[1] << push << ")";
04605 break;
04606 case GRAY_SHADOW:
04607 os << "(" << push << "GRAY_SHADOW" << space << e[0] << space
04608 << e[1] << space << e[2] << space << e[3] << push << ")";
04609 break;
04610 default:
04611
04612
04613 e.printAST(os);
04614
04615 break;
04616 }
04617 break;
04618 default:
04619
04620
04621 e.printAST(os);
04622 }
04623 return os;
04624 }
04625
04626 Theorem TheoryArithOld::inequalityToFind(const Theorem& inequalityThm, bool normalizeRHS) {
04627
04628
04629 int index = (normalizeRHS ? 1 : 0);
04630
04631 TRACE("arith find", "inequalityToFind(", int2string(index) + ", " + inequalityThm.getExpr().toString(), ")");
04632
04633
04634 const Expr& inequality = inequalityThm.getExpr();
04635
04636
04637 Theorem inequalityFindThm;
04638
04639
04640 if (inequality[index].hasFind()) {
04641
04642 Theorem rhsFindThm = inequality[index].getFind();
04643
04644
04645 rhsFindThm = transitivityRule(rhsFindThm, simplify(rhsFindThm.getRHS()));
04646
04647 Expr rhsFind = rhsFindThm.getRHS();
04648 if (rhsFind != inequality[index]) {
04649
04650 vector<unsigned> changed;
04651 vector<Theorem> children;
04652 changed.push_back(index);
04653 children.push_back(rhsFindThm);
04654 rhsFindThm = iffMP(inequalityThm, substitutivityRule(inequality, changed, children));
04655
04656 if (index == 0)
04657 inequalityFindThm = rhsFindThm;
04658 else
04659
04660 if (inequality[0].isRational() && inequality[0].getRational() == 0)
04661 inequalityFindThm = normalize(rhsFindThm);
04662 else
04663 inequalityFindThm = rhsFindThm;
04664 } else
04665 inequalityFindThm = inequalityThm;
04666 } else
04667 inequalityFindThm = inequalityThm;
04668
04669
04670 TRACE("arith find", "inequalityToFind ==>", inequalityFindThm.getExpr(), "");
04671
04672 return inequalityFindThm;
04673 }
04674
04675 void TheoryArithOld::registerAtom(const Expr& e) {
04676
04677 TRACE("arith atoms", "registerAtom(", e.toString(), ")");
04678
04679
04680 formulaAtoms[e] = true;
04681
04682
04683 if (e.isAbsAtomicFormula() && isIneq(e)) {
04684 Expr rightSide = e[1];
04685 Rational leftSide = e[0].getRational();
04686
04687
04688 Expr t1, t2;
04689 Rational c1, c2;
04690 extractTermsFromInequality(e, c1, t1, c2, t2);
04691
04692 if (true) {
04693 TRACE("arith atoms", "registering lower bound for ", t1.toString(), " = " + c1.toString() + ")");
04694 formulaAtomLowerBound[t1].insert(pair<Rational, Expr>(c1, e));
04695
04696
04697 CDMap<Expr, Rational>::iterator lowerBoundFind = termLowerBound.find(t1);
04698 if (lowerBoundFind != termLowerBound.end()) {
04699 Rational boundValue = (*lowerBoundFind).second;
04700 Theorem boundThm = termLowerBoundThm[t1];
04701 Expr boundIneq = boundThm.getExpr();
04702 if (boundValue > c1 || (boundValue == c1 && !(boundIneq.getKind() == LE && e.getKind() == LT))) {
04703 enqueueFact(getCommonRules()->implMP(boundThm, d_rules->implyWeakerInequality(boundIneq, e)));
04704 }
04705 }
04706
04707
04708 CDMap<Expr, Rational>::iterator upperBoundFind = termUpperBound.find(t1);
04709 if (upperBoundFind != termUpperBound.end()) {
04710 Rational boundValue = (*upperBoundFind).second;
04711 Theorem boundThm = termUpperBoundThm[t1];
04712 Expr boundIneq = boundThm.getExpr();
04713 if (boundValue < c1 || (boundValue == c1 && boundIneq.getKind() == LT && e.getKind() == LT)) {
04714 enqueueFact(getCommonRules()->implMP(boundThm, d_rules->implyNegatedInequality(boundIneq, e)));
04715 }
04716 }
04717
04718 TRACE("arith atoms", "registering upper bound for ", t2.toString(), " = " + c2.toString() + ")");
04719 formulaAtomUpperBound[t2].insert(pair<Rational, Expr>(c2, e));
04720 }
04721 }
04722 }
04723
04724 TheoryArithOld::DifferenceLogicGraph::DifferenceLogicGraph(TheoryArithOld* arith, TheoryCore* core, ArithProofRules* rules, Context* context)
04725 : d_pathLenghtThres(&(core->getFlags()["pathlength-threshold"].getInt())),
04726 arith(arith),
04727 core(core),
04728 rules(rules),
04729 unsat_theorem(context),
04730 biggestEpsilon(context, 0, 0),
04731 smallestPathDifference(context, 1, 0),
04732 leGraph(context),
04733 varInCycle(context)
04734 {
04735 }
04736
04737 Theorem TheoryArithOld::DifferenceLogicGraph::getUnsatTheorem() {
04738 return unsat_theorem;
04739 }
04740
04741 bool TheoryArithOld::DifferenceLogicGraph::isUnsat() {
04742 return !getUnsatTheorem().isNull();
04743 }
04744
04745 bool TheoryArithOld::DifferenceLogicGraph::existsEdge(const Expr& x, const Expr& y) {
04746 Expr index = x - y;
04747
04748 Graph::iterator find_le = leGraph.find(index);
04749 if (find_le != leGraph.end()) {
04750 EdgeInfo edge_info = (*find_le).second;
04751 if (edge_info.isDefined()) return true;
04752 }
04753
04754 return false;
04755 }
04756
04757 bool TheoryArithOld::DifferenceLogicGraph::inCycle(const Expr& x) {
04758 return (varInCycle.find(x) != varInCycle.end());
04759 }
04760
04761 TheoryArithOld::DifferenceLogicGraph::Graph::ElementReference TheoryArithOld::DifferenceLogicGraph::getEdge(const Expr& x, const Expr& y) {
04762 Expr index = x - y;
04763 Graph::ElementReference edge_info = leGraph[index];
04764
04765
04766 if (x != y && !edge_info.get().isDefined()) {
04767
04768
04769 core->getResource();
04770
04771 EdgesList::iterator y_it = incomingEdges.find(y);
04772 if (y_it == incomingEdges.end() || (*y_it).second == 0) {
04773 CDList<Expr>* list = new(true) CDList<Expr>(core->getCM()->getCurrentContext());
04774 list->push_back(x);
04775 incomingEdges[y] = list;
04776 } else
04777 ((*y_it).second)->push_back(x);
04778
04779 EdgesList::iterator x_it = outgoingEdges.find(x);
04780 if (x_it == outgoingEdges.end() || (*x_it).second == 0) {
04781 CDList<Expr>* list = new(true) CDList<Expr>(core->getCM()->getCurrentContext());
04782 list->push_back(y);
04783 outgoingEdges[x] = list;
04784 } else
04785 ((*x_it).second)->push_back(y);
04786 }
04787
04788 return edge_info;
04789 }
04790
04791 TheoryArithOld::DifferenceLogicGraph::EpsRational TheoryArithOld::DifferenceLogicGraph::getEdgeWeight(const Expr& x, const Expr& y) {
04792 if (!existsEdge(x, y))
04793 return EpsRational::PlusInfinity;
04794 else {
04795 EdgeInfo edgeInfo = getEdge(x, y).get();
04796 return edgeInfo.length;
04797 }
04798 }
04799
04800
04801 void TheoryArithOld::DifferenceLogicGraph::addEdge(const Expr& x, const Expr& y, const Rational& bound, const Theorem& edge_thm) {
04802
04803 TRACE("arith diff", x, " --> ", y);
04804 DebugAssert(x != y, "addEdge, given two equal expressions!");
04805
04806 if (isUnsat()) return;
04807
04808
04809 if (core->outOfResources()) return;
04810
04811
04812
04813 int kind = (edge_thm.isNull() ? LE : edge_thm.getExpr().getKind());
04814 DebugAssert(kind == LT || kind == LE, "addEdge, not an <= or <!");
04815
04816
04817 Rational k = (kind == LE ? 0 : -1);
04818 EpsRational c(bound, k);
04819
04820
04821 Graph::ElementReference edgeInfoRef = getEdge(x, y);
04822
04823 EdgeInfo edgeInfo = edgeInfoRef.get();
04824
04825 if (!edgeInfo.isDefined() || c <= edgeInfo.length) {
04826
04827
04828 if (edgeInfo.isDefined()) {
04829 EpsRational difference = edgeInfo.length - c;
04830 Rational rationalDifference = difference.getRational();
04831 if (rationalDifference > 0 && rationalDifference < smallestPathDifference) {
04832 smallestPathDifference = rationalDifference;
04833 TRACE("diff model", "smallest path difference : ", smallestPathDifference, "");
04834 }
04835 }
04836 Rational newEpsilon = - c.getEpsilon();
04837 if (newEpsilon > biggestEpsilon) {
04838 biggestEpsilon = newEpsilon;
04839 TRACE("diff model", "biggest epsilon : ", biggestEpsilon, "");
04840 }
04841
04842
04843 edgeInfo.length = c;
04844 edgeInfo.explanation = edge_thm;
04845 edgeInfo.path_length_in_edges = 1;
04846 edgeInfoRef = edgeInfo;
04847
04848
04849
04850 if (existsEdge(y, x)) {
04851 varInCycle[x] = true;
04852 varInCycle[y] = true;
04853 tryUpdate(x, y, x);
04854 if (isUnsat())
04855 return;
04856 }
04857
04858
04859 CDList<Expr>* in_x = incomingEdges[x];
04860 vector<Expr> updated_in_y;
04861 updated_in_y.push_back(x);
04862
04863
04864 if (in_x) {
04865 IF_DEBUG(int total = 0; int updated = 0;);
04866 for (unsigned it = 0; it < in_x->size() && !isUnsat(); it ++) {
04867 const Expr& z = (*in_x)[it];
04868 if (z != arith->zero && z.hasFind() && core->find(z).getRHS() != z) continue;
04869 if (z != y && z != x && x != y) {
04870 IF_DEBUG(total ++;);
04871 TRACE("diff update", "trying with ", z.toString() + " --> ", x.toString());
04872 if (tryUpdate(z, x, y)) {
04873 updated_in_y.push_back(z);
04874 IF_DEBUG(updated++;);
04875 }
04876 }
04877 }
04878 TRACE("diff updates", "Updates : ", int2string(updated), " of " + int2string(total));
04879 }
04880
04881
04882 CDList<Expr>* out_y = outgoingEdges[y];
04883 if (out_y)
04884 for (unsigned it_z1 = 0; it_z1 < updated_in_y.size() && !isUnsat(); it_z1 ++) {
04885 for (unsigned it_z2 = 0; it_z2 < out_y->size() && !isUnsat(); it_z2 ++) {
04886 const Expr& z1 = updated_in_y[it_z1];
04887 const Expr& z2 = (*out_y)[it_z2];
04888 if (z2 != arith->zero && z2.hasFind() && core->find(z2).getRHS() != z2) continue;
04889 if (z1 != z2 && z1 != y && z2 != y)
04890 tryUpdate(z1, y, z2);
04891 }
04892 }
04893
04894 } else {
04895 TRACE("arith propagate", "could have propagated ", edge_thm.getExpr(), edge_thm.isAssump() ? " ASSUMPTION " : "not assumption");
04896
04897 }
04898
04899 }
04900
04901 void TheoryArithOld::DifferenceLogicGraph::getEdgeTheorems(const Expr& x, const Expr& z, const EdgeInfo& edgeInfo, std::vector<Theorem>& outputTheorems) {
04902 TRACE("arith diff", "Getting theorems from ", x, " to " + z.toString() + " length = " + edgeInfo.length.toString() + ", edge_length = " + int2string(edgeInfo.path_length_in_edges));
04903
04904 if (edgeInfo.path_length_in_edges == 1) {
04905 DebugAssert(x == sourceVertex || z == sourceVertex || !edgeInfo.explanation.isNull(), "Edge from " + x.toString() + " to " + z.toString() + " has no theorem!");
04906 if (x != sourceVertex && z != sourceVertex)
04907 outputTheorems.push_back(edgeInfo.explanation);
04908 }
04909 else {
04910 const Expr& y = edgeInfo.in_path_vertex;
04911 EdgeInfo x_y = getEdge(x, y);
04912 DebugAssert(x_y.isDefined(), "getEdgeTheorems: the cycle edge is not defined!");
04913 EdgeInfo y_z = getEdge(y, z);
04914 DebugAssert(y_z.isDefined(), "getEdgeTheorems: the cycle edge is not defined!");
04915 getEdgeTheorems(x, y, x_y, outputTheorems);
04916 getEdgeTheorems(y, z, y_z, outputTheorems);
04917 }
04918 }
04919
04920 void TheoryArithOld::DifferenceLogicGraph::analyseConflict(const Expr& x, int kind) {
04921
04922
04923 Graph::ElementReference x_x_cycle_ref = getEdge(x, x);
04924 EdgeInfo x_x_cycle = x_x_cycle_ref.get();
04925
04926 DebugAssert(x_x_cycle.isDefined(), "analyseConflict: the cycle edge is not defined!");
04927
04928
04929 vector<Theorem> inequalities;
04930
04931
04932 getEdgeTheorems(x, x, x_x_cycle, inequalities);
04933
04934
04935 unsat_theorem = rules->cycleConflict(inequalities);
04936
04937 TRACE("diff unsat", "negative cycle : ", int2string(inequalities.size()), " vertices.");
04938 }
04939
04940 bool TheoryArithOld::DifferenceLogicGraph::tryUpdate(const Expr& x, const Expr& y, const Expr& z) {
04941
04942
04943 if (existsEdge(z, x)) {
04944 varInCycle[x] = true;
04945 varInCycle[y] = true;
04946 varInCycle[z] = true;
04947 }
04948
04949
04950 Graph::ElementReference x_y_le_ref = getEdge(x, y);
04951 EdgeInfo x_y_le = x_y_le_ref;
04952 if (*d_pathLenghtThres >= 0 && x_y_le.path_length_in_edges > *d_pathLenghtThres) return false;
04953
04954 Graph::ElementReference y_z_le_ref = getEdge(y, z);
04955 EdgeInfo y_z_le = y_z_le_ref;
04956 if (*d_pathLenghtThres >= 0 && y_z_le.path_length_in_edges > *d_pathLenghtThres) return false;
04957
04958 Graph::ElementReference x_z_le_ref = getEdge(x, z);
04959 EdgeInfo x_z_le = x_z_le_ref;
04960
04961 bool cycle = (x == z);
04962 bool updated = false;
04963
04964
04965 if (!isUnsat() && x_y_le.isDefined() && y_z_le.isDefined()) {
04966 EpsRational combined_length = x_y_le.length + y_z_le.length;
04967 int combined_edge_length = x_y_le.path_length_in_edges + y_z_le.path_length_in_edges;
04968
04969 if (!x_z_le.isDefined() || combined_length < x_z_le.length ||
04970 (combined_length == x_z_le.length && (combined_edge_length < x_z_le.path_length_in_edges))) {
04971
04972 if (!cycle || combined_length <= EpsRational::Zero) {
04973
04974 if (!cycle || combined_length < EpsRational::Zero) {
04975
04976
04977 if (!cycle) {
04978 EpsRational difference = x_z_le.length - combined_length;
04979 Rational rationalDifference = difference.getRational();
04980 Rational newEpsilon = - x_z_le.length.getEpsilon();
04981 if (rationalDifference > 0 && rationalDifference < smallestPathDifference) {
04982 smallestPathDifference = rationalDifference;
04983 TRACE("diff model", "smallest path difference : ", smallestPathDifference, "");
04984 }
04985 if (newEpsilon > biggestEpsilon) {
04986 biggestEpsilon = newEpsilon;
04987 TRACE("diff model", "biggest epsilon : ", biggestEpsilon, "");
04988 }
04989 }
04990
04991
04992 bool addAndEnqueue = false;
04993 if (core->okToEnqueue() && !combined_length.isInteger())
04994 if (x.getType() == arith->intType() && z.getType() == arith->intType())
04995 addAndEnqueue = true;
04996
04997 x_z_le.length = combined_length;
04998 x_z_le.path_length_in_edges = combined_edge_length;
04999 x_z_le.in_path_vertex = y;
05000 x_z_le_ref = x_z_le;
05001
05002 if (addAndEnqueue) {
05003 vector<Theorem> pathTheorems;
05004 getEdgeTheorems(x, z, x_z_le, pathTheorems);
05005 core->enqueueFact(rules->addInequalities(pathTheorems));
05006 }
05007
05008 TRACE("arith diff", x.toString() + " -- > " + z.toString(), " : ", combined_length.toString());
05009 updated = true;
05010 } else
05011 if (core->okToEnqueue()) {
05012
05013 vector<Theorem> antecedentThms;
05014 getEdgeTheorems(x, y, x_y_le, antecedentThms);
05015 getEdgeTheorems(y, z, y_z_le, antecedentThms);
05016 core->enqueueFact(rules->implyEqualities(antecedentThms));
05017 }
05018
05019
05020 if (updated && !cycle && x != sourceVertex && z != sourceVertex && core->okToEnqueue())
05021 arith->tryPropagate(x, z, x_z_le, LE);
05022
05023 }
05024
05025 if (cycle && combined_length < EpsRational::Zero)
05026 analyseConflict(x, LE);
05027 }
05028 }
05029
05030 return updated;
05031 }
05032
05033 void TheoryArithOld::DifferenceLogicGraph::expandSharedTerm(const Expr& x) {
05034
05035 }
05036
05037 TheoryArithOld::DifferenceLogicGraph::~DifferenceLogicGraph() {
05038 for (EdgesList::iterator it = incomingEdges.begin(), it_end = incomingEdges.end(); it != it_end; it ++) {
05039 if ((*it).second) {
05040 delete (*it).second;
05041 free ((*it).second);
05042 }
05043 }
05044 for (EdgesList::iterator it = outgoingEdges.begin(), it_end = outgoingEdges.end(); it != it_end; it ++) {
05045 if ((*it).second) {
05046 delete (*it).second;
05047 free ((*it).second);
05048 }
05049 }
05050 }
05051
05052 void TheoryArithOld::tryPropagate(const Expr& x, const Expr& y, const DifferenceLogicGraph::EdgeInfo& x_y_edge, int kind) {
05053
05054 TRACE("diff atoms", "trying propagation", " x = " + x.toString(), " y = " + y.toString());
05055
05056
05057
05058
05059
05060
05061
05062
05063 vector<Expr> t1_summands;
05064 t1_summands.push_back(rat(0));
05065 if (y != zero) t1_summands.push_back(y);
05066
05067
05068 if (x != zero) t1_summands.push_back(canon(rat(-1)*x).getRHS());
05069 Expr t1 = canon(plusExpr(t1_summands)).getRHS();
05070
05071 TRACE("diff atoms", "trying propagation", " t1 = " + t1.toString(), "");
05072
05073
05074 Rational c1 = - x_y_edge.length.getRational();
05075
05076
05077
05078 AtomsMap::iterator find = formulaAtomLowerBound.find(t1);
05079 AtomsMap::iterator find_end = formulaAtomLowerBound.end();
05080 if (find != find_end) {
05081 set< pair<Rational, Expr> >::iterator bounds = (*find).second.begin();
05082 set< pair<Rational, Expr> >::iterator bounds_end = (*find).second.end();
05083 while (bounds != bounds_end) {
05084 const Expr& implied = (*bounds).second;
05085
05086 if ((*bounds).first < c1 || (implied.getKind() == LE && (*bounds).first == c1)) {
05087 TRACE("diff atoms", "found propagation", "", "");
05088
05089
05090
05091 vector<Theorem> antecedentThms;
05092 diffLogicGraph.getEdgeTheorems(x, y, x_y_edge, antecedentThms);
05093 Theorem impliedThm = d_rules->implyWeakerInequalityDiffLogic(antecedentThms, implied);
05094 enqueueFact(impliedThm);
05095 }
05096 bounds ++;
05097 }
05098 }
05099
05100
05101
05102
05103
05104 find = formulaAtomUpperBound.find(t1);
05105 find_end = formulaAtomUpperBound.end();
05106 if (find != find_end) {
05107 set< pair<Rational, Expr> >::iterator bounds = (*find).second.begin();
05108 set< pair<Rational, Expr> >::iterator bounds_end = (*find).second.end();
05109 while (bounds != bounds_end) {
05110 const Expr& implied = (*bounds).second;
05111
05112 if ((*bounds).first < c1) {
05113 TRACE("diff atoms", "found negated propagation", "", "");
05114 vector<Theorem> antecedentThms;
05115 diffLogicGraph.getEdgeTheorems(x, y, x_y_edge, antecedentThms);
05116 Theorem impliedThm = d_rules->implyNegatedInequalityDiffLogic(antecedentThms, implied);
05117 enqueueFact(impliedThm);
05118 }
05119 bounds ++;
05120 }
05121 }
05122 }
05123
05124 void TheoryArithOld::DifferenceLogicGraph::computeModel() {
05125
05126
05127 if (sourceVertex.isNull()) {
05128 Theorem thm_exists_zero = arith->getCommonRules()->varIntroSkolem(arith->zero);
05129 sourceVertex = thm_exists_zero.getExpr()[1];
05130 }
05131
05132
05133 Theorem thm;
05134
05135
05136 EdgesList::iterator vertexIt = incomingEdges.begin();
05137 EdgesList::iterator vertexItEnd = incomingEdges.end();
05138 for (; vertexIt != vertexItEnd; vertexIt ++) {
05139 Expr vertex = (*vertexIt).first;
05140 if (core->find(vertex).getRHS() != vertex) continue;
05141 if (vertex != sourceVertex && !existsEdge(sourceVertex, vertex))
05142 addEdge(sourceVertex, vertex, 0, thm);
05143 }
05144 vertexIt = outgoingEdges.begin();
05145 vertexItEnd = outgoingEdges.end();
05146 for (; vertexIt != vertexItEnd; vertexIt ++) {
05147 Expr vertex = (*vertexIt).first;
05148 if (core->find(vertex).getRHS() != vertex) continue;
05149 if (vertex != sourceVertex && !existsEdge(sourceVertex, vertex))
05150 addEdge(sourceVertex, vertex, 0, thm);
05151 }
05152
05153
05154 if (!existsEdge(sourceVertex, arith->zero))
05155 addEdge(sourceVertex, arith->zero, 0, thm);
05156
05157
05158
05159
05160
05161 }
05162
05163 Rational TheoryArithOld::DifferenceLogicGraph::getValuation(const Expr& x) {
05164
05165
05166 if (x.isRational()) return x.getRational();
05167
05168
05169 if (x == sourceVertex) return 0;
05170
05171
05172 Graph::ElementReference x_le_c_ref = getEdge(sourceVertex, x);
05173 EdgeInfo x_le_c = x_le_c_ref;
05174
05175
05176 Graph::ElementReference zero_le_c_ref = getEdge(sourceVertex, arith->zero);
05177 EdgeInfo zero_le_c = zero_le_c_ref;
05178
05179 TRACE("diff model", "zero adjustment: ", zero_le_c.length.getRational(), "");
05180 TRACE("diff model", "zero adjustment (eps): ", zero_le_c.length.getEpsilon(), "");
05181
05182
05183 Rational epsAdjustment = (biggestEpsilon > 0 ? (x_le_c.length.getEpsilon() - zero_le_c.length.getEpsilon()) * smallestPathDifference / (2 * (biggestEpsilon + 1)) : 0);
05184 Rational value = x_le_c.length.getRational() + epsAdjustment;
05185
05186 TRACE("diff model" , "biggest epsilon: ", biggestEpsilon, "");
05187 TRACE("diff model" , "smallestPathDifference: ", smallestPathDifference, "");
05188 TRACE("diff model" , "x_le_c.getEpsilon: ", x_le_c.length.getEpsilon(), "");
05189 TRACE("diff model" , "x_le_c.length: ", x_le_c.length.getRational(), "");
05190
05191
05192 value = zero_le_c.length.getRational() - value;
05193
05194 TRACE("diff model", "Value of ", x, " : " + value.toString());
05195
05196
05197 return value;
05198 }
05199
05200
05201 const TheoryArithOld::DifferenceLogicGraph::EpsRational TheoryArithOld::DifferenceLogicGraph::EpsRational::PlusInfinity(PLUS_INFINITY);
05202
05203 const TheoryArithOld::DifferenceLogicGraph::EpsRational TheoryArithOld::DifferenceLogicGraph::EpsRational::MinusInfinity(MINUS_INFINITY);
05204
05205 const TheoryArithOld::DifferenceLogicGraph::EpsRational TheoryArithOld::DifferenceLogicGraph::EpsRational::Zero;
05206
05207 void TheoryArithOld::addMultiplicativeSignSplit(const Theorem& case_split_thm) {
05208 multiplicativeSignSplits.push_back(case_split_thm);
05209 }
05210
05211 bool TheoryArithOld::addPairToArithOrder(const Expr& smaller, const Expr& bigger) {
05212 TRACE("arith var order", "addPairToArithOrder(" + smaller.toString(), ", ", bigger.toString() + ")");
05213
05214 if (!isReal(smaller.getType()) && !isInt(smaller.getType())) return false;
05215 if (!isReal(bigger.getType()) && !isInt(bigger.getType())) return false;
05216
05217 FatalAssert(!d_graph.lessThan(smaller, bigger), "The pair (" + bigger.toString() + "," + smaller.toString() + ") is already in the order");
05218
05219 d_graph.addEdge(smaller, bigger);
05220 return true;
05221 }
05222
05223 bool TheoryArithOld::isNonlinearSumTerm(const Expr& term) {
05224 if (isPow(term)) return true;
05225 if (!isMult(term)) return false;
05226 int vars = 0;
05227 for (int j = 0; j < term.arity(); j ++)
05228 if (isPow(term[j])) return true;
05229 else if (isLeaf(term[j])) {
05230 vars ++;
05231 if (vars > 1) return true;
05232 }
05233 return false;
05234 }
05235
05236 bool TheoryArithOld::isNonlinearEq(const Expr& e) {
05237
05238 DebugAssert(e.isEq(), "TheoryArithOld::isNonlinear: expecting an equation" + e.toString());
05239
05240 const Expr& lhs = e[0];
05241 const Expr& rhs = e[1];
05242
05243 if (isNonlinearSumTerm(lhs) || isNonlinearSumTerm(rhs)) return true;
05244
05245
05246 for (int i = 0; i < lhs.arity(); i ++)
05247 if (isNonlinearSumTerm(lhs[i])) return true;
05248
05249
05250 for (int i = 0; i < rhs.arity(); i ++)
05251 if (isNonlinearSumTerm(rhs[i])) return true;
05252
05253 return false;
05254 }
05255
05256
05257 bool TheoryArithOld::isPowersEquality(const Expr& eq, Expr& power1, Expr& power2) {
05258
05259 DebugAssert(eq.isEq(), "TheoryArithOld::isPowersEquality, expecting an equality got " + eq.toString());
05260
05261 if (!isPlus(eq[0])) return false;
05262 if (eq[0].arity() != 3) return false;
05263 if (!(eq[0][0].isRational()) || !(eq[0][0].getRational() == 0)) return false;
05264
05265
05266 Expr term1 = eq[0][1];
05267 Rational term1_c;
05268 if (isPow(term1)) {
05269 term1_c = 1;
05270 power1 = term1;
05271 } else
05272 if (isMult(term1) && term1.arity() == 2) {
05273 if (term1[0].isRational()) {
05274 term1_c = term1[0].getRational();
05275 if (isPow(term1[1])) {
05276 if (term1_c == 1) power1 = term1[1];
05277 else if (term1_c == -1) power2 = term1[1];
05278 else return false;
05279 } else return false;
05280 } else return false;
05281 } else return false;
05282
05283
05284 Expr term2 = eq[0][2];
05285 Rational term2_c;
05286 if (isPow(term2)) {
05287 term2_c = 1;
05288 power1 = term2;
05289 } else
05290 if (isMult(term2) && term2.arity() == 2) {
05291 if (term2[0].isRational()) {
05292 term2_c = term2[0].getRational();
05293 if (isPow(term2[1])) {
05294 if (term2_c == 1) power1 = term2[1];
05295 else if (term2_c == -1) power2 = term2[1];
05296 else return false;
05297 } else return false;
05298 } else return false;
05299 } else return false;
05300
05301
05302 if (term1_c == term2_c) return false;
05303
05304
05305 if (!power1[0].isRational()) return false;
05306 if (!power2[0].isRational()) return false;
05307 if (power1[0].getRational() != power2[0].getRational()) return false;
05308
05309
05310 return true;
05311 }
05312
05313 bool TheoryArithOld::isPowerEquality(const Expr& eq, Rational& constant, Expr& power1) {
05314 DebugAssert(eq.isEq(), "TheoryArithOld::isPowerEquality, expecting an equality got " + eq.toString());
05315
05316 if (!isPlus(eq[0])) return false;
05317 if (eq[0].arity() != 2) return false;
05318 if (!eq[0][0].isRational()) return false;
05319
05320 constant = eq[0][0].getRational();
05321
05322 Expr term = eq[0][1];
05323 if (isPow(term)) {
05324 power1 = term;
05325 constant = -constant;
05326 } else
05327 if (isMult(term) && term.arity() == 2) {
05328 if (term[0].isRational() && isPow(term[1])) {
05329 Rational term2_c = term[0].getRational();
05330 if (term2_c == 1) {
05331 power1 = term[1];
05332 constant = -constant;
05333 } else if (term2_c == -1) {
05334 power1 = term[1];
05335 return true;
05336 } else return false;
05337 } else return false;
05338 } else return false;
05339
05340
05341 if (!power1[0].isRational()) return false;
05342 if (!power1[0].getRational().isInteger()) return false;
05343
05344 return true;
05345 }
05346
05347 int TheoryArithOld::termDegree(const Expr& e) {
05348 if (isLeaf(e)) return 1;
05349 if (isPow(e)) return termDegree(e[1]) * e[0].getRational().getInt();
05350 if (isMult(e)) {
05351 int degree = 0;
05352 for (int i = 0; i < e.arity(); i ++) degree += termDegree(e[i]);
05353 return degree;
05354 }
05355 return 0;
05356 }
05357
05358 bool TheoryArithOld::canPickEqMonomial(const Expr& right)
05359 {
05360 Expr::iterator istart = right.begin();
05361 Expr::iterator iend = right.end();
05362
05363
05364 istart++;
05365 for(Expr::iterator i = istart; i != iend; ++i) {
05366
05367 Expr leaf;
05368 Rational coeff;
05369
05370
05371 if (isLeaf(*i)) {
05372 leaf = *i;
05373 coeff = 1;
05374 } else if (isMult(*i) && (*i).arity() == 2 && (*i)[0].isRational() && isLeaf((*i)[1])) {
05375 leaf = (*i)[1];
05376 coeff = abs((*i)[0].getRational());
05377 } else
05378 continue;
05379
05380
05381 if (!isIntegerThm(leaf).isNull())
05382 if (coeff != 1 && coeff != -1)
05383 continue;
05384
05385
05386 Expr::iterator j;
05387 for (j = istart; j != iend; ++j)
05388 if (j != i && isLeafIn(leaf, *j))
05389 break;
05390 if (j == iend)
05391 return true;
05392 }
05393
05394 return false;
05395 }
05396
05397 bool TheoryArithOld::isBounded(const Expr& t, BoundsQueryType queryType) {
05398 TRACE("arith shared", "isBounded(", t.toString(), ")");
05399 return hasUpperBound(t, queryType) && hasLowerBound(t, queryType);
05400 }
05401
05402 TheoryArithOld::DifferenceLogicGraph::EpsRational TheoryArithOld::getUpperBound(const Expr& t, BoundsQueryType queryType)
05403 {
05404 TRACE("arith shared", "getUpperBound(", t.toString(), ")");
05405
05406
05407 if (t.isRational()) {
05408 TRACE("arith shared", "getUpperBound(", t.toString(), ") ==> " + t.getRational().toString());
05409 return t.getRational();
05410 }
05411
05412
05413 CDMap<Expr, DifferenceLogicGraph::EpsRational>::iterator find_t = termUpperBounded.find(t);
05414 if (find_t != termUpperBounded.end()) {
05415 TRACE("arith shared", "getUpperBound(", t.toString(), ") ==> " + (*find_t).second.toString());
05416 return (*find_t).second;
05417 } else if (queryType == QueryWithCacheAll) {
05418
05419 TRACE("arith shared", "getUpperBound(", t.toString(), ") ==> +inf");
05420 return DifferenceLogicGraph::EpsRational::PlusInfinity;
05421 }
05422
05423
05424 DifferenceLogicGraph::EpsRational upperBound = DifferenceLogicGraph::EpsRational::PlusInfinity;
05425
05426
05427 if (!isLeaf(t)) {
05428 if (isMult(t)) {
05429
05430 if (!isNonlinearSumTerm(t)) {
05431
05432 Expr c, v;
05433 separateMonomial(t, c, v);
05434
05435 if (c.getRational() > 0) upperBound = getUpperBound(v);
05436 else upperBound = getLowerBound(v);
05437 if (upperBound.isFinite()) upperBound = upperBound * c.getRational();
05438 else upperBound = DifferenceLogicGraph::EpsRational::PlusInfinity;
05439 }
05440 } else if (isPlus(t)) {
05441
05442 upperBound = DifferenceLogicGraph::EpsRational::Zero;
05443 for (int i = 0; i < t.arity(); i ++) {
05444 Expr t_i = t[i];
05445 DifferenceLogicGraph::EpsRational t_i_upperBound = getUpperBound(t_i, queryType);
05446 if (t_i_upperBound.isFinite()) upperBound = upperBound + t_i_upperBound;
05447 else {
05448 upperBound = DifferenceLogicGraph::EpsRational::PlusInfinity;
05449
05450 if (queryType == QueryWithCacheLeavesAndConstrainedComputation) {
05451 for(; i < t.arity() && isConstrainedAbove(t[i], QueryWithCacheLeaves); i ++);
05452 if (i == t.arity()) {
05453 TRACE("arith shared", "getUpperBound(", t.toString(), ") ==> constrained");
05454 termConstrainedAbove[t] = true;
05455 }
05456 break;
05457 } else break;
05458 }
05459 }
05460 }
05461 }
05462
05463
05464 if (upperBound.isFinite()) {
05465 termUpperBounded[t] = upperBound;
05466 termConstrainedAbove[t] = true;
05467 }
05468
05469
05470 TRACE("arith shared", "getUpperBound(", t.toString(), ") ==> " + upperBound.toString());
05471 return upperBound;
05472 }
05473
05474 TheoryArithOld::DifferenceLogicGraph::EpsRational TheoryArithOld::getLowerBound(const Expr& t, BoundsQueryType queryType)
05475 {
05476 TRACE("arith shared", "getLowerBound(", t.toString(), ")");
05477
05478
05479 if (t.isRational()) {
05480 TRACE("arith shared", "getLowerBound(", t.toString(), ") ==> " + t.getRational().toString());
05481 return t.getRational();
05482 }
05483
05484
05485 CDMap<Expr, DifferenceLogicGraph::EpsRational>::iterator t_find = termLowerBounded.find(t);
05486 if (t_find != termLowerBounded.end()) {
05487 TRACE("arith shared", "getLowerBound(", t.toString(), ") ==> " + (*t_find).second.toString());
05488 return (*t_find).second;
05489 } else if (queryType == QueryWithCacheAll) {
05490
05491 TRACE("arith shared", "getLowerBound(", t.toString(), ") ==> -inf");
05492 return DifferenceLogicGraph::EpsRational::MinusInfinity;
05493 }
05494
05495
05496 DifferenceLogicGraph::EpsRational lowerBound = DifferenceLogicGraph::EpsRational::MinusInfinity;
05497
05498
05499 if (!isLeaf(t)) {
05500 if (isMult(t)) {
05501
05502 if (!isNonlinearSumTerm(t)) {
05503
05504 Expr c, v;
05505 separateMonomial(t, c, v);
05506
05507 if (c.getRational() > 0) lowerBound = getLowerBound(v);
05508 else lowerBound = getUpperBound(v);
05509 if (lowerBound.isFinite()) lowerBound = lowerBound * c.getRational();
05510 else lowerBound = DifferenceLogicGraph::EpsRational::MinusInfinity;
05511 }
05512 } else if (isPlus(t)) {
05513
05514 lowerBound = DifferenceLogicGraph::EpsRational::Zero;
05515 for (int i = 0; i < t.arity(); i ++) {
05516 Expr t_i = t[i];
05517 DifferenceLogicGraph::EpsRational t_i_lowerBound = getLowerBound(t_i, queryType);
05518 if (t_i_lowerBound.isFinite()) lowerBound = lowerBound + t_i_lowerBound;
05519 else {
05520 lowerBound = DifferenceLogicGraph::EpsRational::MinusInfinity;
05521
05522 if (queryType == QueryWithCacheLeavesAndConstrainedComputation) {
05523 for(; i < t.arity() && isConstrainedBelow(t[i], QueryWithCacheLeaves); i ++);
05524 if (i == t.arity()) {
05525 TRACE("arith shared", "getLowerBound(", t.toString(), ") ==> constrained");
05526 termConstrainedBelow[t] = true;
05527 }
05528 break;
05529 } else break;
05530 }
05531 }
05532 }
05533 }
05534
05535
05536 if (lowerBound.isFinite()) {
05537 termLowerBounded[t] = lowerBound;
05538 termConstrainedBelow[t] = true;
05539 }
05540
05541
05542 TRACE("arith shared", "getLowerBound(", t.toString(), ") ==> " + lowerBound.toString());
05543 return lowerBound;
05544 }
05545
05546 int TheoryArithOld::computeTermBounds()
05547 {
05548 int computeTermBoundsConstrainedCount = 0;
05549
05550 vector<Expr> sorted_vars;
05551
05552 if (!diffLogicOnly) d_graph.getVerticesTopological(sorted_vars);
05553
05554 else {
05555 diffLogicGraph.getVariables(sorted_vars);
05556 IF_DEBUG(
05557 diffLogicGraph.writeGraph(cerr);
05558 )
05559 }
05560
05561
05562 for (int i = sorted_vars.size() - 1; i >= 0; i --)
05563 {
05564
05565 Expr v = sorted_vars[i];
05566
05567
05568 if (v.hasFind() && find(v).getRHS() != v) continue;
05569
05570 TRACE("arith shared", "processing: ", v.toString(), "");
05571
05572
05573 if (isIntegerThm(v).isNull() && !d_inModelCreation) continue;
05574
05575
05576 if (!isConstrained(v, QueryWithCacheAll)) {
05577
05578
05579 bool constrainedAbove = isConstrained(v, QueryWithCacheAll);
05580
05581
05582 DifferenceLogicGraph::EpsRational upperBound = diffLogicGraph.getEdgeWeight(v, zero);
05583 if (!constrainedAbove) constrainedAbove = upperBound.isFinite();
05584
05585
05586 if (!diffLogicOnly) {
05587 ExprMap<CDList<Ineq> *>::iterator v_left_find = d_inequalitiesLeftDB.find(v);
05588
05589 if (v_left_find != d_inequalitiesLeftDB.end()) {
05590
05591 CDList<Ineq>*& left_list = (*v_left_find).second;
05592 if (left_list && left_list->size() > 0) {
05593 for (unsigned ineq_i = 0; ineq_i < left_list->size(); ineq_i ++) {
05594
05595 Ineq ineq = (*left_list)[ineq_i];
05596
05597 Expr rhs = ineq.ineq().getExpr()[1];
05598
05599 if (rhs.hasFind() && find(rhs).getRHS() != rhs) continue;
05600
05601 DifferenceLogicGraph::EpsRational currentUpperBound = getUpperBound(rhs, (constrainedAbove ? QueryWithCacheLeaves : QueryWithCacheLeavesAndConstrainedComputation));
05602 if (currentUpperBound.isFinite() && (!upperBound.isFinite() || currentUpperBound < upperBound)) {
05603 upperBound = currentUpperBound;
05604 constrainedAbove = true;
05605 }
05606
05607 if (!constrainedAbove) constrainedAbove = isConstrainedAbove(rhs, QueryWithCacheAll);
05608 }
05609 }
05610 }
05611 }
05612
05613 else if (!constrainedAbove) {
05614
05615 if (!diffLogicGraph.hasIncoming(v)) constrainedAbove = false;
05616
05617
05618
05619 else if (diffLogicGraph.inCycle(v)) constrainedAbove = true;
05620
05621
05622
05623
05624
05625
05626 else constrainedAbove = d_inModelCreation;
05627 }
05628
05629
05630 if (constrainedAbove) termConstrainedAbove[v] = true;
05631 if (upperBound.isFinite()) termUpperBounded[v] = upperBound;
05632
05633
05634 bool constrainedBelow = isConstrainedBelow(v, QueryWithCacheAll);
05635
05636
05637 DifferenceLogicGraph::EpsRational lowerBound = diffLogicGraph.getEdgeWeight(zero, v);
05638 if (lowerBound.isFinite()) lowerBound = -lowerBound;
05639 else lowerBound = DifferenceLogicGraph::EpsRational::MinusInfinity;
05640 if (!constrainedBelow) constrainedBelow = lowerBound.isFinite();
05641
05642
05643 if (!diffLogicOnly) {
05644 ExprMap<CDList<Ineq> *>::iterator v_right_find = d_inequalitiesRightDB.find(v);
05645
05646 if (v_right_find != d_inequalitiesRightDB.end()) {
05647
05648 CDList<Ineq>*& right_list = (*v_right_find).second;
05649 if (right_list && right_list->size() > 0) {
05650 for (unsigned ineq_i = 0; ineq_i < right_list->size(); ineq_i ++) {
05651
05652 Ineq ineq = (*right_list)[ineq_i];
05653
05654 Expr lhs = ineq.ineq().getExpr()[0];
05655
05656 if (lhs.hasFind() && find(lhs).getRHS() != lhs) continue;
05657
05658 DifferenceLogicGraph::EpsRational currentLowerBound = getLowerBound(lhs, (constrainedBelow ? QueryWithCacheLeaves : QueryWithCacheLeavesAndConstrainedComputation));
05659 if (currentLowerBound.isFinite() && (!lowerBound.isFinite() || currentLowerBound > lowerBound)) {
05660 lowerBound = currentLowerBound;
05661 constrainedBelow = true;
05662 }
05663
05664 if (!constrainedBelow) constrainedBelow = isConstrainedBelow(lhs, QueryWithCacheAll);
05665 }
05666 }
05667 }
05668 }
05669
05670 else if (!constrainedBelow) {
05671
05672 if (!diffLogicGraph.hasOutgoing(v)) constrainedBelow = false;
05673
05674
05675
05676 else if (diffLogicGraph.inCycle(v)) constrainedBelow = true;
05677
05678
05679
05680
05681
05682
05683 else constrainedBelow = d_inModelCreation;
05684 }
05685
05686
05687 if (constrainedBelow) termConstrainedBelow[v] = true;
05688 if (lowerBound.isFinite()) termLowerBounded[v] = lowerBound;
05689
05690
05691 if (constrainedAbove && constrainedBelow) computeTermBoundsConstrainedCount ++;
05692
05693 TRACE("arith shared", (constrainedAbove && constrainedBelow ? "constrained " : "unconstrained "), "", "");
05694 } else
05695 computeTermBoundsConstrainedCount ++;
05696 }
05697
05698 TRACE("arith shared", "number of constrained variables : ", int2string(computeTermBoundsConstrainedCount), " of " + int2string(sorted_vars.size()));
05699
05700 return computeTermBoundsConstrainedCount;
05701 }
05702
05703 bool TheoryArithOld::isConstrainedAbove(const Expr& t, BoundsQueryType queryType)
05704 {
05705 TRACE("arith shared", "isConstrainedAbove(", t.toString(), ")");
05706
05707
05708 if (t.isRational()) {
05709 TRACE("arith shared", "isConstrainedAbove() ==> true", "", "");
05710 return true;
05711 }
05712
05713
05714 CDMap<Expr, bool>::iterator t_find = termConstrainedAbove.find(t);
05715 if (t_find != termConstrainedAbove.end()) {
05716 TRACE("arith shared", "isConstrainedAbove() ==> true", "", "");
05717 return true;
05718 }
05719 else if (queryType == QueryWithCacheAll) {
05720 TRACE("arith shared", "isConstrainedAbove() ==> false", "", "");
05721 return false;
05722 }
05723
05724 bool constrainedAbove = true;
05725
05726 if (isLeaf(t)) {
05727
05728 constrainedAbove = false;
05729 } else {
05730 if (isMult(t)) {
05731
05732
05733 if (!isNonlinearSumTerm(t)) {
05734
05735 Expr c, v;
05736 separateMonomial(t, c, v);
05737
05738 if (c.getRational() > 0) constrainedAbove = isConstrainedAbove(v, queryType);
05739 else constrainedAbove = isConstrainedBelow(v, queryType);
05740 }
05741 } else if (isPlus(t)) {
05742
05743 for (int i = 0; i < t.arity() && constrainedAbove; i ++)
05744 if (!isConstrainedAbove(t[i])) constrainedAbove = false;
05745 }
05746 }
05747
05748
05749 if (constrainedAbove) termConstrainedAbove[t] = true;
05750
05751 TRACE("arith shared", "isConstrainedAbove() ==> ", constrainedAbove ? "true" : "false", "");
05752
05753
05754 return constrainedAbove;
05755 }
05756
05757 bool TheoryArithOld::isConstrainedBelow(const Expr& t, BoundsQueryType queryType)
05758 {
05759 TRACE("arith shared", "isConstrainedBelow(", t.toString(), ")");
05760
05761
05762 if (t.isRational()) return true;
05763
05764
05765 CDMap<Expr, bool>::iterator t_find = termConstrainedBelow.find(t);
05766 if (t_find != termConstrainedBelow.end()) {
05767 TRACE("arith shared", "isConstrainedBelow() ==> true", "", "");
05768 return true;
05769 }
05770 else if (queryType == QueryWithCacheAll) {
05771 TRACE("arith shared", "isConstrainedBelow() ==> false", "", "");
05772 return false;
05773 }
05774
05775 bool constrainedBelow = true;
05776
05777 if (isLeaf(t)) {
05778
05779 constrainedBelow = false;
05780 } else {
05781 if (isMult(t)) {
05782
05783
05784 if (!isNonlinearSumTerm(t)) {
05785
05786 Expr c, v;
05787 separateMonomial(t, c, v);
05788
05789 if (c.getRational() > 0) constrainedBelow = isConstrainedBelow(v, queryType);
05790 else constrainedBelow = isConstrainedAbove(v, queryType);
05791 }
05792 } else if (isPlus(t)) {
05793
05794 constrainedBelow = true;
05795 for (int i = 0; i < t.arity() && constrainedBelow; i ++)
05796 if (!isConstrainedBelow(t[i]))
05797 constrainedBelow = false;
05798 }
05799 }
05800
05801
05802 if (constrainedBelow) termConstrainedBelow[t] = true;
05803
05804 TRACE("arith shared", "isConstrainedBelow() ==> ", constrainedBelow ? "true" : "false", "");
05805
05806
05807 return constrainedBelow;
05808 }
05809
05810 bool TheoryArithOld::isConstrained(const Expr& t, bool intOnly, BoundsQueryType queryType)
05811 {
05812 TRACE("arith shared", "isConstrained(", t.toString(), ")");
05813
05814 if (intOnly && isIntegerThm(t).isNull()) return false;
05815 bool result = (isConstrainedAbove(t, queryType) && isConstrainedBelow(t, queryType));
05816 TRACE("arith shared", "isConstrained(", t.toString(), (result ? ") ==> true " : ") ==> false ") );
05817 return result;
05818 }
05819
05820 bool TheoryArithOld::DifferenceLogicGraph::hasIncoming(const Expr& x)
05821 {
05822 EdgesList::iterator find_x = incomingEdges.find(x);
05823
05824
05825 if (find_x == incomingEdges.end()) return false;
05826
05827
05828 CDList<Expr>*& list = (*find_x).second;
05829 if (!list) return false;
05830
05831
05832 if (sourceVertex.isNull())
05833 return list->size() > 0;
05834 else
05835 return list->size() > 1;
05836 }
05837
05838 bool TheoryArithOld::DifferenceLogicGraph::hasOutgoing(const Expr& x)
05839 {
05840 EdgesList::iterator find_x = outgoingEdges.find(x);
05841
05842
05843 if (find_x == outgoingEdges.end()) return false;
05844
05845
05846 CDList<Expr>*& list = (*find_x).second;
05847 if (!list) return false;
05848
05849
05850 return list->size() > 0;
05851 }
05852
05853 void TheoryArithOld::DifferenceLogicGraph::getVariables(vector<Expr>& variables)
05854 {
05855 set<Expr> vars_set;
05856
05857 EdgesList::iterator incoming_it = incomingEdges.begin();
05858 EdgesList::iterator incoming_it_end = incomingEdges.end();
05859 while (incoming_it != incoming_it_end) {
05860 Expr var = (*incoming_it).first;
05861 if (var != sourceVertex)
05862 vars_set.insert(var);
05863 incoming_it ++;
05864 }
05865
05866 EdgesList::iterator outgoing_it = outgoingEdges.begin();
05867 EdgesList::iterator outgoing_it_end = outgoingEdges.end();
05868 while (outgoing_it != outgoing_it_end) {
05869 Expr var = (*outgoing_it).first;
05870 if (var != sourceVertex)
05871 vars_set.insert(var);
05872 outgoing_it ++;
05873 }
05874
05875 set<Expr>::iterator set_it = vars_set.begin();
05876 set<Expr>::iterator set_it_end = vars_set.end();
05877 while (set_it != set_it_end) {
05878 variables.push_back(*set_it);
05879 set_it ++;
05880 }
05881 }
05882
05883 void TheoryArithOld::DifferenceLogicGraph::writeGraph(ostream& out) {
05884 return;
05885 out << "digraph G {" << endl;
05886
05887 EdgesList::iterator incoming_it = incomingEdges.begin();
05888 EdgesList::iterator incoming_it_end = incomingEdges.end();
05889 while (incoming_it != incoming_it_end) {
05890
05891 Expr var_u = (*incoming_it).first;
05892
05893 CDList<Expr>* edges = (*incoming_it).second;
05894 if (edges)
05895 for (unsigned edge_i = 0; edge_i < edges->size(); edge_i ++) {
05896 Expr var_v = (*edges)[edge_i];
05897 out << var_u.toString() << " -> " << var_v.toString() << endl;
05898 }
05899
05900 incoming_it ++;
05901 }
05902
05903 out << "}" << endl;
05904 }