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