00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030 #define _CVC3_TRUSTED_
00031
00032 #include "arith_theorem_producer_old.h"
00033 #include "theory_core.h"
00034 #include "theory_arith_old.h"
00035 #include <algorithm>
00036
00037 using namespace std;
00038 using namespace CVC3;
00039
00040
00041
00042
00043
00044 ArithProofRules* TheoryArithOld::createProofRulesOld() {
00045 return new ArithTheoremProducerOld(theoryCore()->getTM(), this);
00046 }
00047
00048
00049
00050
00051
00052
00053 #define CLASS_NAME "ArithTheoremProducerOld"
00054
00055
00056
00057 Theorem ArithTheoremProducerOld::varToMult(const Expr& e) {
00058 Proof pf;
00059 if(withProof()) pf = newPf("var_to_mult", e);
00060 return newRWTheorem(e, (rat(1) * e), Assumptions::emptyAssump(), pf);
00061 }
00062
00063
00064
00065 Theorem ArithTheoremProducerOld::uMinusToMult(const Expr& e) {
00066 Proof pf;
00067 if(withProof()) pf = newPf("uminus_to_mult", e);
00068 return newRWTheorem((-e), (rat(-1) * e), Assumptions::emptyAssump(), pf);
00069 }
00070
00071
00072
00073 Theorem ArithTheoremProducerOld::minusToPlus(const Expr& x, const Expr& y)
00074 {
00075 Proof pf;
00076 if(withProof()) pf = newPf("minus_to_plus", x, y);
00077 return newRWTheorem((x-y), (x + (rat(-1) * y)), Assumptions::emptyAssump(), pf);
00078 }
00079
00080
00081
00082
00083 Theorem ArithTheoremProducerOld::canonUMinusToDivide(const Expr& e) {
00084 Proof pf;
00085 if(withProof()) pf = newPf("canon_uminus", e);
00086 return newRWTheorem((-e), (e / rat(-1)), Assumptions::emptyAssump(), pf);
00087 }
00088
00089
00090
00091
00092 Theorem ArithTheoremProducerOld::canonDivideConst(const Expr& c,
00093 const Expr& d) {
00094
00095 if(CHECK_PROOFS) {
00096 CHECK_SOUND(isRational(c),
00097 CLASS_NAME "::canonDivideConst:\n c not a constant: "
00098 + c.toString());
00099 CHECK_SOUND(isRational(d),
00100 CLASS_NAME "::canonDivideConst:\n d not a constant: "
00101 + d.toString());
00102 }
00103 Proof pf;
00104 if(withProof())
00105 pf = newPf("canon_divide_const", c, d, d_hole);
00106 const Rational& dr = d.getRational();
00107 return newRWTheorem((c/d), (rat(dr==0? 0 : (c.getRational()/dr))), Assumptions::emptyAssump(), pf);
00108 }
00109
00110
00111 Theorem ArithTheoremProducerOld::canonDivideMult(const Expr& cx,
00112 const Expr& d) {
00113
00114 if(CHECK_PROOFS) {
00115 CHECK_SOUND(isMult(cx) && isRational(cx[0]),
00116 CLASS_NAME "::canonDivideMult:\n "
00117 "Not a (c * x) expression: "
00118 + cx.toString());
00119 CHECK_SOUND(isRational(d),
00120 CLASS_NAME "::canonDivideMult:\n "
00121 "d is not a constant: " + d.toString());
00122 }
00123 const Rational& dr = d.getRational();
00124 Rational cdr(dr==0? 0 : (cx[0].getRational()/dr));
00125 Expr cd(rat(cdr));
00126 Proof pf;
00127 if(withProof())
00128 pf = newPf("canon_divide_mult", cx[0], cx[1], d);
00129
00130 if(cdr == 1)
00131 return newRWTheorem((cx/d), (cx[1]), Assumptions::emptyAssump(), pf);
00132 else if(cdr == 0)
00133 return newRWTheorem((cx/d), cd, Assumptions::emptyAssump(), pf);
00134 else
00135 return newRWTheorem((cx/d), (cd*cx[1]), Assumptions::emptyAssump(), pf);
00136 }
00137
00138
00139 Theorem ArithTheoremProducerOld::canonDividePlus(const Expr& sum, const Expr& d) {
00140 if(CHECK_PROOFS) {
00141 CHECK_SOUND(isPlus(sum) && sum.arity() >= 2 && isRational(sum[0]),
00142 CLASS_NAME "::canonUMinusPlus:\n "
00143 "Expr is not a canonical sum: "
00144 + sum.toString());
00145 CHECK_SOUND(isRational(d),
00146 CLASS_NAME "::canonUMinusPlus:\n "
00147 "d is not a const: " + d.toString());
00148 }
00149
00150 Proof pf;
00151 if(withProof())
00152 pf = newPf("canon_divide_plus", rat(sum.arity()),
00153 sum.begin(), sum.end());
00154 vector<Expr> newKids;
00155 for(Expr::iterator i=sum.begin(), iend=sum.end(); i!=iend; ++i)
00156 newKids.push_back((*i)/d);
00157
00158 return newRWTheorem((sum/d), (plusExpr(newKids)), Assumptions::emptyAssump(), pf);
00159 }
00160
00161
00162 Theorem ArithTheoremProducerOld::canonDivideVar(const Expr& e, const Expr& d) {
00163 if(CHECK_PROOFS) {
00164 CHECK_SOUND(isRational(d),
00165 CLASS_NAME "::canonDivideVar:\n "
00166 "d is not a const: " + d.toString());
00167 }
00168 Proof pf;
00169
00170 if(withProof())
00171 pf = newPf("canon_divide_var", e);
00172
00173 const Rational& dr = d.getRational();
00174 if(dr == 1)
00175 return newRWTheorem(e/d, e, Assumptions::emptyAssump(), pf);
00176 if(dr == 0)
00177 return newRWTheorem(e/d, d, Assumptions::emptyAssump(), pf);
00178 else
00179 return newRWTheorem(e/d, rat(1/dr) * e, Assumptions::emptyAssump(), pf);
00180 }
00181
00182
00183
00184
00185
00186
00187
00188
00189
00190
00191
00192
00193
00194
00195
00196
00197 Expr ArithTheoremProducerOld::simplifiedMultExpr(std::vector<Expr> & mulKids)
00198 {
00199 DebugAssert(mulKids.size() >= 1 && mulKids[0].isRational(), "");
00200 if (mulKids.size() == 1) {
00201 return mulKids[0];
00202 }
00203 if ((mulKids[0] == rat(1)) && mulKids.size() == 2) {
00204 return mulKids[1];
00205 }
00206 else
00207 return multExpr(mulKids);
00208 }
00209
00210 Expr ArithTheoremProducerOld::canonMultConstMult(const Expr & c,
00211 const Expr & e)
00212 {
00213
00214
00215
00216 DebugAssert(c.isRational() && e.getKind() == MULT, "");
00217 std::vector<Expr> mulKids;
00218 DebugAssert ((e.arity() > 1) && (e[0].isRational()),
00219 "ArithTheoremProducerOld::canonMultConstMult: "
00220 "a canonized MULT expression must have arity "
00221 "greater than 1: and first child must be "
00222 "rational " + e.toString());
00223 Expr::iterator i = e.begin();
00224 mulKids.push_back(rat(c.getRational() * (*i).getRational()));
00225 ++i;
00226 for(; i != e.end(); ++i) {
00227 mulKids.push_back(*i);
00228 }
00229 return simplifiedMultExpr(mulKids);
00230 }
00231
00232 Expr ArithTheoremProducerOld::canonMultConstPlus(const Expr & e1,
00233 const Expr & e2)
00234 {
00235 DebugAssert(e1.isRational() && e2.getKind() == PLUS &&
00236 e2.arity() > 0, "");
00237
00238
00239
00240 std::vector<Theorem> thmPlusVector;
00241 Expr::iterator i = e2.begin();
00242 for(; i!= e2.end(); ++i) {
00243 thmPlusVector.push_back(canonMultMtermMterm(e1*(*i)));
00244 }
00245
00246 Theorem thmPlus1 =
00247 d_theoryArith->substitutivityRule(e2.getOp(), thmPlusVector);
00248 return thmPlus1.getRHS();
00249 }
00250
00251 Expr ArithTheoremProducerOld::canonMultPowPow(const Expr & e1,
00252 const Expr & e2)
00253 {
00254 DebugAssert(e1.getKind() == POW && e2.getKind() == POW, "");
00255
00256 Expr leaf1 = e1[1];
00257 Expr leaf2 = e2[1];
00258 Expr can_expr;
00259 if (leaf1 == leaf2) {
00260 Rational rsum = e1[0].getRational() + e2[0].getRational();
00261 if (rsum == 0) {
00262 return rat(1);
00263 }
00264 else if (rsum == 1) {
00265 return leaf1;
00266 }
00267 else
00268 {
00269 return powExpr(rat(rsum), leaf1);
00270 }
00271 }
00272 else
00273 {
00274 std::vector<Expr> mulKids;
00275 mulKids.push_back(rat(1));
00276
00277 if (leaf1 < leaf2) {
00278 mulKids.push_back(e2);
00279 mulKids.push_back(e1);
00280 }
00281 else
00282 {
00283 mulKids.push_back(e1);
00284 mulKids.push_back(e2);
00285 }
00286
00287 return simplifiedMultExpr(mulKids);
00288 }
00289 }
00290
00291 Expr ArithTheoremProducerOld::canonMultPowLeaf(const Expr & e1,
00292 const Expr & e2)
00293 {
00294 DebugAssert(e1.getKind() == POW, "");
00295
00296 Expr leaf1 = e1[1];
00297 Expr leaf2 = e2;
00298 Expr can_expr;
00299 if (leaf1 == leaf2) {
00300 Rational rsum = e1[0].getRational() + 1;
00301 if (rsum == 0) {
00302 return rat(1);
00303 }
00304 else if (rsum == 1) {
00305 return leaf1;
00306 }
00307 else
00308 {
00309 return powExpr(rat(rsum), leaf1);
00310 }
00311 }
00312 else
00313 {
00314 std::vector<Expr> mulKids;
00315 mulKids.push_back(rat(1));
00316
00317 if (leaf1 < leaf2) {
00318 mulKids.push_back(e2);
00319 mulKids.push_back(e1);
00320 }
00321 else
00322 {
00323 mulKids.push_back(e1);
00324 mulKids.push_back(e2);
00325 }
00326 return simplifiedMultExpr(mulKids);
00327 }
00328 }
00329
00330 Expr ArithTheoremProducerOld::canonMultLeafLeaf(const Expr & e1,
00331 const Expr & e2)
00332 {
00333
00334 Expr leaf1 = e1;
00335 Expr leaf2 = e2;
00336 Expr can_expr;
00337 if (leaf1 == leaf2) {
00338 return powExpr(rat(2), leaf1);
00339 }
00340 else
00341 {
00342 std::vector<Expr> mulKids;
00343 mulKids.push_back(rat(1));
00344
00345 if (leaf1 < leaf2) {
00346 mulKids.push_back(e2);
00347 mulKids.push_back(e1);
00348 }
00349 else
00350 {
00351 mulKids.push_back(e1);
00352 mulKids.push_back(e2);
00353 }
00354 return simplifiedMultExpr(mulKids);
00355 }
00356 }
00357
00358 Expr ArithTheoremProducerOld::canonMultLeafOrPowMult(const Expr & e1,
00359 const Expr & e2)
00360 {
00361 DebugAssert(e2.getKind() == MULT, "");
00362
00363
00364
00365
00366 Expr leaf1 = e1.getKind() == POW ? e1[1] : e1;
00367 std::vector<Expr> mulKids;
00368 DebugAssert(e2.arity() > 1, "MULT expr must have arity 2 or more");
00369 Expr::iterator i = e2.begin();
00370
00371 mulKids.push_back(*i);
00372 ++i;
00373
00374 for(; i != e2.end(); ++i) {
00375 Expr leaf2 = ((*i).getKind() == POW) ? (*i)[1] : (*i);
00376 if (leaf1 == leaf2) {
00377 Rational r1 = e1.getKind() == POW ? e1[0].getRational() : 1;
00378 Rational r2 =
00379 ((*i).getKind() == POW ? (*i)[0].getRational() : 1);
00380
00381
00382 if (r1 + r2 != 0) {
00383 if (r1 + r2 == 1) {
00384 mulKids.push_back(leaf1);
00385 }
00386 else
00387 {
00388 mulKids.push_back(powExpr(rat(r1 + r2), leaf1));
00389 }
00390 }
00391 break;
00392 }
00393
00394
00395
00396
00397 else if (leaf2 < leaf1) {
00398 mulKids.push_back(e1);
00399 mulKids.push_back(*i);
00400 break;
00401 }
00402 else
00403 mulKids.push_back(*i);
00404 }
00405 if (i == e2.end()) {
00406 mulKids.push_back(e1);
00407 }
00408 else
00409 {
00410
00411 for (++i; i != e2.end(); ++i) {
00412 mulKids.push_back(*i);
00413 }
00414 }
00415 return simplifiedMultExpr(mulKids);
00416 }
00417
00418
00419
00420 class MonomialLess {
00421 public:
00422 bool operator()(const Expr& e1, const Expr& e2) const {
00423 return ArithTheoremProducerOld::greaterthan(e1,e2);
00424 }
00425 };
00426
00427 typedef map<Expr,Rational,MonomialLess> MonomMap;
00428
00429 Expr
00430 ArithTheoremProducerOld::canonCombineLikeTerms(const std::vector<Expr> & sumExprs)
00431 {
00432 Rational constant = 0;
00433 MonomMap sumHashMap;
00434 vector<Expr> sumKids;
00435
00436
00437
00438 std::vector<Expr>::const_iterator i = sumExprs.begin();
00439 for (; i != sumExprs.end(); ++i) {
00440 Expr mul = *i;
00441 if (mul.isRational()) {
00442 constant = constant + mul.getRational();
00443 }
00444 else {
00445 switch (mul.getKind()) {
00446 case MULT: {
00447 std::vector<Expr> mulKids;
00448 DebugAssert(mul.arity() > 1 && mul[0].isRational(),"");
00449 mulKids.push_back(rat(1));
00450 Expr::iterator j = mul.begin();
00451 ++j;
00452 for (; j!= mul.end(); ++j) {
00453 mulKids.push_back(*j);
00454 }
00455
00456
00457 Expr tempExpr = mulKids.size() > 2 ? multExpr(mulKids): mulKids[1];
00458 MonomMap::iterator i=sumHashMap.find(tempExpr);
00459 if (i == sumHashMap.end()) {
00460 sumHashMap[tempExpr] = mul[0].getRational();
00461 }
00462 else {
00463 (*i).second += mul[0].getRational();
00464 }
00465 }
00466 break;
00467 default: {
00468 MonomMap::iterator i=sumHashMap.find(mul);
00469
00470 if (i == sumHashMap.end()) {
00471 sumHashMap[mul] = 1;
00472 }
00473 else {
00474 (*i).second += 1;
00475 }
00476 break;
00477 }
00478 }
00479 }
00480 }
00481
00482 sumKids.push_back(rat(constant));
00483 MonomMap::iterator j = sumHashMap.begin(), jend=sumHashMap.end();
00484 for(; j != jend; ++j) {
00485 if ((*j).second != 0)
00486 sumKids.push_back
00487 (canonMultMtermMterm(rat((*j).second) * (*j).first).getRHS());
00488 }
00489
00490
00491
00492
00493
00494
00495
00496
00497
00498
00499
00500
00501 if ((constant == 0) && (sumKids.size() == 2)) {
00502 return sumKids[1];
00503 }
00504 else if (sumKids.size() == 1) {
00505 return sumKids[0];
00506 }
00507 else
00508 return plusExpr(sumKids);
00509 }
00510
00511 Expr ArithTheoremProducerOld::canonMultLeafOrPowOrMultPlus(const Expr & e1,
00512 const Expr & e2)
00513 {
00514 DebugAssert(e2.getKind() == PLUS, "");
00515
00516
00517
00518
00519
00520
00521 std::vector<Expr> sumExprs;
00522
00523 Expr::iterator i = e2.begin();
00524 for (; i != e2.end(); ++i) {
00525 sumExprs.push_back(canonMultMtermMterm(e1 * (*i)).getRHS());
00526 }
00527 return canonCombineLikeTerms(sumExprs);
00528 }
00529
00530 Expr ArithTheoremProducerOld::canonMultPlusPlus(const Expr & e1,
00531 const Expr & e2)
00532 {
00533 DebugAssert(e1.getKind() == PLUS && e2.getKind() == PLUS, "");
00534
00535
00536
00537 std::vector<Expr> sumExprs;
00538
00539 Expr::iterator i = e1.begin();
00540 for (; i != e1.end(); ++i) {
00541 Expr::iterator j = e2.begin();
00542 for (; j != e2.end(); ++j) {
00543 sumExprs.push_back(canonMultMtermMterm((*i) * (*j)).getRHS());
00544 }
00545 }
00546 return canonCombineLikeTerms(sumExprs);
00547 }
00548
00549
00550
00551
00552
00553 Theorem
00554 ArithTheoremProducerOld::canonMultMtermMterm(const Expr& e)
00555 {
00556 if(CHECK_PROOFS) {
00557 CHECK_SOUND(isMult(e) && e.arity() == 2,
00558 "canonMultMtermMterm: e = "+e.toString());
00559 }
00560 Proof pf;
00561 Expr rhs;
00562 const Expr& e1 = e[0];
00563 const Expr& e2 = e[1];
00564 string cmmm = "canon_mult_mterm_mterm";
00565
00566 if (e1.isRational()) {
00567
00568 const Rational& c = e1.getRational();
00569 if (c == 0)
00570 return canonMultZero(e2);
00571 else if (c == 1)
00572 return canonMultOne(e2);
00573 else {
00574 switch (e2.getKind()) {
00575 case RATIONAL_EXPR :
00576
00577 return canonMultConstConst(e1,e2);
00578 break;
00579
00580 case POW:
00581
00582
00583 return d_theoryArith->reflexivityRule (e);
00584
00585 break;
00586 case MULT:
00587 rhs = canonMultConstMult(e1,e2);
00588 if(withProof()) pf = newPf(cmmm,e,rhs);
00589 return newRWTheorem(e, rhs, Assumptions::emptyAssump(), pf);
00590 break;
00591 case PLUS:
00592 rhs = canonMultConstPlus(e1,e2);
00593 if(withProof()) pf = newPf(cmmm,e,rhs);
00594 return newRWTheorem(e, rhs, Assumptions::emptyAssump(), pf);
00595 break;
00596 default:
00597
00598
00599 return d_theoryArith->reflexivityRule(e);
00600 break;
00601 }
00602 }
00603 }
00604 else if (e1.getKind() == POW) {
00605 switch (e2.getKind()) {
00606 case RATIONAL_EXPR:
00607
00608 return canonMultMtermMterm(e2 * e1);
00609 break;
00610 case POW:
00611 rhs = canonMultPowPow(e1,e2);
00612 if(withProof()) pf = newPf(cmmm,e,rhs);
00613 return newRWTheorem(e,rhs, Assumptions::emptyAssump(), pf);
00614 break;
00615 case MULT:
00616 rhs = canonMultLeafOrPowMult(e1,e2);
00617 if(withProof()) pf = newPf(cmmm,e,rhs);
00618 return newRWTheorem(e, rhs, Assumptions::emptyAssump(), pf);
00619 break;
00620 case PLUS:
00621 rhs = canonMultLeafOrPowOrMultPlus(e1,e2);
00622 if(withProof()) pf = newPf(cmmm,e,rhs);
00623 return newRWTheorem(e, rhs, Assumptions::emptyAssump(), pf);
00624 break;
00625 default:
00626 rhs = canonMultPowLeaf(e1,e2);
00627 if(withProof()) pf = newPf(cmmm,e,rhs);
00628 return newRWTheorem(e,rhs, Assumptions::emptyAssump(), pf);
00629 break;
00630 }
00631 }
00632 else if (e1.getKind() == MULT) {
00633 switch (e2.getKind()) {
00634 case RATIONAL_EXPR:
00635 case POW:
00636
00637 return canonMultMtermMterm(e2 * e1);
00638 break;
00639 case MULT:
00640 {
00641
00642 Expr result = e2;
00643 Expr::iterator i = e1.begin();
00644 for (; i != e1.end(); ++i) {
00645 result = canonMultMtermMterm((*i) * result).getRHS();
00646 }
00647 if(withProof()) pf = newPf(cmmm,e,result);
00648 return newRWTheorem(e, result, Assumptions::emptyAssump(), pf);
00649 }
00650 break;
00651 case PLUS:
00652 rhs = canonMultLeafOrPowOrMultPlus(e1,e2);
00653 if(withProof()) pf = newPf(cmmm,e,rhs);
00654 return newRWTheorem(e,rhs, Assumptions::emptyAssump(), pf);
00655 break;
00656 default:
00657
00658
00659 return canonMultMtermMterm(e2 * e1);
00660 break;
00661 }
00662 }
00663 else if (e1.getKind() == PLUS) {
00664 switch (e2.getKind()) {
00665 case RATIONAL_EXPR:
00666 case POW:
00667 case MULT:
00668
00669 return canonMultMtermMterm(e2 * e1);
00670 break;
00671 case PLUS:
00672 rhs = canonMultPlusPlus(e1,e2);
00673 if(withProof()) pf = newPf(cmmm,e,rhs);
00674 return newRWTheorem(e, rhs, Assumptions::emptyAssump(), pf);
00675 break;
00676 default:
00677
00678
00679 return canonMultMtermMterm(e2 * e1);
00680 break;
00681 }
00682 }
00683 else {
00684
00685 switch (e2.getKind()) {
00686 case RATIONAL_EXPR:
00687
00688 return canonMultMtermMterm(e2 * e1);
00689 break;
00690 case POW:
00691 rhs = canonMultPowLeaf(e2,e1);
00692 if(withProof()) pf = newPf(cmmm,e,rhs);
00693 return newRWTheorem(e, rhs, Assumptions::emptyAssump(), pf);
00694 break;
00695 case MULT:
00696 rhs = canonMultLeafOrPowMult(e1,e2);;
00697 if(withProof()) pf = newPf(cmmm,e,rhs);
00698 return newRWTheorem(e, rhs, Assumptions::emptyAssump(), pf);
00699 break;
00700 case PLUS:
00701 rhs = canonMultLeafOrPowOrMultPlus(e1,e2);
00702 if(withProof()) pf = newPf(cmmm,e,rhs);
00703 return newRWTheorem(e, rhs, Assumptions::emptyAssump(), pf);
00704 break;
00705 default:
00706
00707 rhs = canonMultLeafLeaf(e1,e2);
00708 if(withProof()) pf = newPf(cmmm,e,rhs);
00709 return newRWTheorem(e, rhs, Assumptions::emptyAssump(), pf);
00710 break;
00711 }
00712 }
00713 FatalAssert(false, "Unreachable");
00714 return newRWTheorem(e, rhs, Assumptions::emptyAssump(), pf);
00715 }
00716
00717
00718 Theorem
00719 ArithTheoremProducerOld::canonPlus(const Expr& e)
00720 {
00721 Proof pf;
00722
00723 if (withProof()) {
00724 pf = newPf("canon_plus", e);
00725 }
00726 DebugAssert(e.getKind() == PLUS, "");
00727
00728
00729
00730 std::vector<Expr> sumKids;
00731 Expr::iterator i = e.begin();
00732 for(; i != e.end(); ++i) {
00733 if ((*i).getKind() != PLUS) {
00734 sumKids.push_back(*i);
00735 }
00736 else
00737 {
00738 Expr::iterator j = (*i).begin();
00739 for(; j != (*i).end(); ++j)
00740 sumKids.push_back(*j);
00741 }
00742 }
00743 Expr val = canonCombineLikeTerms(sumKids);
00744 if (withProof()) {
00745 pf = newPf("canon_plus", e, val);
00746 }
00747 return newRWTheorem(e, val, Assumptions::emptyAssump(), pf);
00748 }
00749
00750
00751 Theorem
00752 ArithTheoremProducerOld::canonMult(const Expr& e)
00753 {
00754 Proof pf;
00755 TRACE("arith canon", "canonMult(", e.toString(), ")");
00756 DebugAssert(e.getKind() == MULT && e.arity() > 1, "");
00757 Expr::iterator i = e.begin();
00758 Expr result = *i;
00759 ++i;
00760 for (; i != e.end(); ++i) {
00761 result = canonMultMtermMterm(result * (*i)).getRHS();
00762 }
00763 if (withProof()) {
00764 pf = newPf("canon_mult", e,result);
00765 }
00766
00767
00768 if (d_theoryArith->nonlinearSignSplit()) {
00769
00770
00771 Expr positive = d_em->trueExpr();
00772 Expr negative = d_em->falseExpr();
00773 vector<Expr> zero;
00774
00775
00776 int count_non_trivial = 0;
00777 int count_constants = 0;
00778
00779
00780
00781 for (i = e.begin(); i != e.end(); ++i) {
00782 Expr current = (*i);
00783
00784 if (isPlus(current)) count_non_trivial ++;
00785 if (current.isRational()) count_constants ++;
00786 if (isPow(current) && current[0].getRational() < 0) {
00787
00788 count_non_trivial = 0;
00789 break;
00790 }
00791
00792 zero.push_back(current.eqExpr(rat(0)));
00793 positive = Expr(XOR, positive, ltExpr(current, rat(0)));
00794 negative = Expr(XOR, negative, ltExpr(current, rat(0)));
00795 }
00796
00797 if (count_non_trivial > 0 && !count_constants == (e.arity() - 1)) {
00798
00799 Expr zero_lemma = orExpr(zero).iffExpr(result.eqExpr(rat(0)));
00800 Expr positive_lemma = positive.impExpr(geExpr(result, rat(0)));
00801 Expr negative_lemma = negative.impExpr(leExpr(result, rat(0)));
00802 Expr lemma = positive_lemma.andExpr(negative_lemma.andExpr(zero_lemma));
00803
00804 Proof split_pf;
00805 if (withProof()) split_pf = newPf("multiplicative_sign_split", e, lemma);
00806 Theorem case_split_thm = newTheorem(lemma, Assumptions::emptyAssump(), split_pf);
00807
00808 TRACE("arith nonlinear", "adding sign split: ", lemma, "");
00809
00810 d_theoryArith->addMultiplicativeSignSplit(case_split_thm);
00811 }
00812 }
00813
00814 return newRWTheorem(e, result, Assumptions::emptyAssump(), pf);
00815 }
00816
00817
00818 Theorem
00819 ArithTheoremProducerOld::canonInvertConst(const Expr& e)
00820 {
00821 if(CHECK_PROOFS)
00822 CHECK_SOUND(isRational(e), "expecting a rational: e = "+e.toString());
00823
00824 Proof pf;
00825
00826 if (withProof()) {
00827 pf = newPf("canon_invert_const", e);
00828 }
00829 const Rational& er = e.getRational();
00830 return newRWTheorem((rat(1)/e), rat(er==0? 0 : (1/er)), Assumptions::emptyAssump(), pf);
00831 }
00832
00833
00834 Theorem
00835 ArithTheoremProducerOld::canonInvertLeaf(const Expr& e)
00836 {
00837 Proof pf;
00838
00839 if (withProof()) {
00840 pf = newPf("canon_invert_leaf", e);
00841 }
00842 return newRWTheorem((rat(1)/e), powExpr(rat(-1), e), Assumptions::emptyAssump(), pf);
00843 }
00844
00845
00846 Theorem
00847 ArithTheoremProducerOld::canonInvertPow(const Expr& e)
00848 {
00849 DebugAssert(e.getKind() == POW, "expecting a rational"+e[0].toString());
00850
00851 Proof pf;
00852
00853 if (withProof()) {
00854 pf = newPf("canon_invert_pow", e);
00855 }
00856 if (e[0].getRational() == -1)
00857 return newRWTheorem((rat(1)/e), e[1], Assumptions::emptyAssump(), pf);
00858 else
00859 return newRWTheorem((rat(1)/e),
00860 powExpr(rat(-e[0].getRational()), e[1]),
00861 Assumptions::emptyAssump(),
00862 pf);
00863 }
00864
00865 Theorem
00866 ArithTheoremProducerOld::canonInvertMult(const Expr& e)
00867 {
00868 DebugAssert(e.getKind() == MULT, "expecting a rational"+e[0].toString());
00869
00870 Proof pf;
00871
00872 if (withProof()) {
00873 pf = newPf("canon_invert_mult", e);
00874 }
00875
00876 DebugAssert(e.arity() > 1, "MULT should have arity > 1"+e.toString());
00877 Expr result = canonInvert(e[0]).getRHS();
00878 for (int i = 1; i < e.arity(); ++i) {
00879 result =
00880 canonMultMtermMterm(result * canonInvert(e[i]).getRHS()).getRHS();
00881 }
00882 return newRWTheorem((rat(1)/e), result, Assumptions::emptyAssump(), pf);
00883 }
00884
00885
00886
00887
00888 Theorem
00889 ArithTheoremProducerOld::canonInvert(const Expr& e)
00890 {
00891 DebugAssert(e.getKind() != PLUS,
00892 "Cannot do inverse on a PLUS"+e.toString());
00893 switch (e.getKind()) {
00894 case RATIONAL_EXPR:
00895 return canonInvertConst(e);
00896 break;
00897 case POW:
00898 return canonInvertPow(e);
00899 break;
00900 case MULT:
00901 return canonInvertMult(e);
00902 break;
00903 default:
00904
00905 return canonInvertLeaf(e);
00906 break;
00907 }
00908 }
00909
00910
00911 Theorem ArithTheoremProducerOld::moveSumConstantRight(const Expr& e) {
00912
00913
00914 if (CHECK_PROOFS) {
00915 CHECK_SOUND(isIneq(e) || e.isEq(), "moveSumConstantRight: input must be Eq or Ineq: " + e.toString());
00916 CHECK_SOUND(isRational(e[0]) || isPlus(e[0]), "moveSumConstantRight: left side must be a canonised sum: " + e.toString());
00917 CHECK_SOUND(isRational(e[1]) && e[1].getRational() == 0, "moveSumConstantRight: right side must be 0: " + e.toString());
00918 }
00919
00920
00921 Rational r = 0;
00922
00923
00924 Expr right = e[0];
00925
00926
00927 vector<Expr> sumTerms;
00928
00929
00930 if (!right.isRational())
00931 for(Expr::iterator it = right.begin(); it != right.end(); it ++) {
00932
00933 if ((*it).isRational()) r = r + (*it).getRational();
00934
00935 else sumTerms.push_back((*it));
00936 }
00937
00938
00939 Expr transformed;
00940 if (sumTerms.size() > 1)
00941
00942 transformed = Expr(e.getKind(), plusExpr(sumTerms), rat(-r));
00943 else
00944
00945 transformed = Expr(e.getKind(), sumTerms[0], rat(-r));
00946
00947
00948
00949 Proof pf;
00950 if (withProof()) pf = newPf("arithm_sum_constant_right", e);
00951
00952
00953 return newRWTheorem(e, transformed, Assumptions::emptyAssump(), pf);
00954 }
00955
00956 Theorem
00957 ArithTheoremProducerOld::canonDivide(const Expr& e)
00958 {
00959 DebugAssert(e.getKind() == DIVIDE, "Expecting Divide"+e.toString());
00960 Proof pf;
00961
00962 if (withProof()) {
00963 pf = newPf("canon_invert_divide", e);
00964 }
00965
00966 Theorem thm = newRWTheorem(e, e[0]*(canonInvert(e[1]).getRHS()), Assumptions::emptyAssump(), pf);
00967
00968 return d_theoryArith->transitivityRule(thm, canonMult(thm.getRHS()));
00969 }
00970
00971
00972
00973
00974 Theorem
00975 ArithTheoremProducerOld::canonMultTermConst(const Expr& c, const Expr& t) {
00976 Proof pf;
00977 if(CHECK_PROOFS) {
00978 CHECK_SOUND(isRational(c),
00979 CLASS_NAME "::canonMultTermConst:\n "
00980 "c is not a constant: " + c.toString());
00981 }
00982 if(withProof()) pf = newPf("canon_mult_term_const", c, t);
00983 return newRWTheorem((t*c), (c*t), Assumptions::emptyAssump(), pf);
00984 }
00985
00986
00987
00988 Theorem
00989 ArithTheoremProducerOld::canonMultTerm1Term2(const Expr& t1, const Expr& t2) {
00990
00991
00992 if(CHECK_PROOFS) {
00993 CHECK_SOUND(false, "Fatal Error: We don't support multiplication"
00994 "of two non constant terms at this time "
00995 + t1.toString() + " and " + t2.toString());
00996 }
00997 return Theorem();
00998 }
00999
01000
01001
01002 Theorem ArithTheoremProducerOld::canonMultZero(const Expr& e) {
01003 Proof pf;
01004 if(withProof()) pf = newPf("canon_mult_zero", e);
01005 return newRWTheorem((rat(0)*e), rat(0), Assumptions::emptyAssump(), pf);
01006 }
01007
01008
01009
01010 Theorem ArithTheoremProducerOld::canonMultOne(const Expr& e) {
01011 Proof pf;
01012 if(withProof()) pf = newPf("canon_mult_one", e);
01013 return newRWTheorem((rat(1)*e), e, Assumptions::emptyAssump(), pf);
01014 }
01015
01016
01017
01018 Theorem
01019 ArithTheoremProducerOld::canonMultConstConst(const Expr& c1, const Expr& c2) {
01020 Proof pf;
01021 if(CHECK_PROOFS) {
01022 CHECK_SOUND(isRational(c1),
01023 CLASS_NAME "::canonMultConstConst:\n "
01024 "c1 is not a constant: " + c1.toString());
01025 CHECK_SOUND(isRational(c2),
01026 CLASS_NAME "::canonMultConstConst:\n "
01027 "c2 is not a constant: " + c2.toString());
01028 }
01029 if(withProof()) pf = newPf("canon_mult_const_const", c1, c2);
01030 return
01031 newRWTheorem((c1*c2), rat(c1.getRational()*c2.getRational()), Assumptions::emptyAssump(), pf);
01032 }
01033
01034
01035
01036 Theorem
01037 ArithTheoremProducerOld::canonMultConstTerm(const Expr& c1,
01038 const Expr& c2,const Expr& t) {
01039 Proof pf;
01040 if(CHECK_PROOFS) {
01041 CHECK_SOUND(isRational(c1),
01042 CLASS_NAME "::canonMultConstTerm:\n "
01043 "c1 is not a constant: " + c1.toString());
01044 CHECK_SOUND(isRational(c2),
01045 CLASS_NAME "::canonMultConstTerm:\n "
01046 "c2 is not a constant: " + c2.toString());
01047 }
01048
01049 if(withProof()) pf = newPf("canon_mult_const_term", c1, c2, t);
01050 return
01051 newRWTheorem(c1*(c2*t), rat(c1.getRational()*c2.getRational())*t, Assumptions::emptyAssump(), pf);
01052 }
01053
01054
01055
01056 Theorem
01057 ArithTheoremProducerOld::canonMultConstSum(const Expr& c1, const Expr& sum) {
01058 Proof pf;
01059 std::vector<Expr> sumKids;
01060
01061 if(CHECK_PROOFS) {
01062 CHECK_SOUND(isRational(c1),
01063 CLASS_NAME "::canonMultConstTerm:\n "
01064 "c1 is not a constant: " + c1.toString());
01065 CHECK_SOUND(PLUS == sum.getKind(),
01066 CLASS_NAME "::canonMultConstTerm:\n "
01067 "the kind must be a PLUS: " + sum.toString());
01068 }
01069 Expr::iterator i = sum.begin();
01070 for(; i != sum.end(); ++i)
01071 sumKids.push_back(c1*(*i));
01072 Expr ret = plusExpr(sumKids);
01073 if(withProof()) pf = newPf("canon_mult_const_sum", c1, sum, ret);
01074 return newRWTheorem((c1*sum),ret , Assumptions::emptyAssump(), pf);
01075 }
01076
01077
01078
01079 Theorem
01080 ArithTheoremProducerOld::canonPowConst(const Expr& e) {
01081 if(CHECK_PROOFS) {
01082 CHECK_SOUND(e.getKind() == POW && e.arity() == 2
01083 && e[0].isRational() && e[1].isRational(),
01084 "ArithTheoremProducerOld::canonPowConst("+e.toString()+")");
01085 }
01086 const Rational& p = e[0].getRational();
01087 const Rational& base = e[1].getRational();
01088 if(CHECK_PROOFS) {
01089 CHECK_SOUND(p.isInteger(),
01090 "ArithTheoremProducerOld::canonPowConst("+e.toString()+")");
01091 }
01092 Expr res;
01093 if (base == 0 && p < 0) {
01094 res = rat(0);
01095 }
01096 else res = rat(pow(p, base));
01097 Proof pf;
01098 if(withProof())
01099 pf = newPf("canon_pow_const", e);
01100 return newRWTheorem(e, res, Assumptions::emptyAssump(), pf);
01101 }
01102
01103
01104
01105
01106 Theorem
01107 ArithTheoremProducerOld::canonFlattenSum(const Expr& e) {
01108 Proof pf;
01109 std::vector<Expr> sumKids;
01110 if(CHECK_PROOFS) {
01111 CHECK_SOUND(PLUS == e.getKind(),
01112 CLASS_NAME "::canonFlattenSum:\n"
01113 "input must be a PLUS:" + e.toString());
01114 }
01115
01116 Expr::iterator i = e.begin();
01117 for(; i != e.end(); ++i){
01118 if (PLUS != (*i).getKind())
01119 sumKids.push_back(*i);
01120 else {
01121 Expr::iterator j = (*i).begin();
01122 for(; j != (*i).end(); ++j)
01123 sumKids.push_back(*j);
01124 }
01125 }
01126 Expr ret = plusExpr(sumKids);
01127 if(withProof()) pf = newPf("canon_flatten_sum", e,ret);
01128 return newRWTheorem(e,ret, Assumptions::emptyAssump(), pf);
01129 }
01130
01131
01132
01133 Theorem
01134 ArithTheoremProducerOld::canonComboLikeTerms(const Expr& e) {
01135 Proof pf;
01136 std::vector<Expr> sumKids;
01137 ExprMap<Rational> sumHashMap;
01138 Rational constant = 0;
01139
01140 if(CHECK_PROOFS) {
01141 Expr::iterator k = e.begin();
01142 for(; k != e.end(); ++k)
01143 CHECK_SOUND(!isPlus(*k),
01144 CLASS_NAME "::canonComboLikeTerms:\n"
01145 "input must be a flattened PLUS:" + k->toString());
01146 }
01147 Expr::iterator i = e.begin();
01148 for(; i != e.end(); ++i){
01149 if(i->isRational())
01150 constant = constant + i->getRational();
01151 else {
01152 if (!isMult(*i)) {
01153 if(0 == sumHashMap.count((*i)))
01154 sumHashMap[*i] = 1;
01155 else
01156 sumHashMap[*i] += 1;
01157 }
01158 else {
01159 if(0 == sumHashMap.count((*i)[1]))
01160 sumHashMap[(*i)[1]] = (*i)[0].getRational();
01161 else
01162 sumHashMap[(*i)[1]] = sumHashMap[(*i)[1]] + (*i)[0].getRational();
01163 }
01164 }
01165 }
01166
01167 sumKids.push_back(rat(constant));
01168 ExprMap<Rational>::iterator j = sumHashMap.begin();
01169 for(; j != sumHashMap.end(); ++j) {
01170 if(0 == (*j).second)
01171 ;
01172 else if (1 == (*j).second)
01173 sumKids.push_back((*j).first);
01174 else
01175 sumKids.push_back(rat((*j).second) * (*j).first);
01176 }
01177
01178
01179
01180
01181 Expr ret;
01182 if(2 == sumKids.size() && 0 == constant) ret = sumKids[1];
01183 else if (1 == sumKids.size()) ret = sumKids[0];
01184 else ret = plusExpr(sumKids);
01185
01186 if(withProof()) pf = newPf("canon_combo_like_terms",e,ret);
01187 return newRWTheorem(e, ret, Assumptions::emptyAssump(), pf);
01188 }
01189
01190
01191
01192 Theorem ArithTheoremProducerOld::multEqZero(const Expr& expr)
01193 {
01194 Proof pf;
01195 vector<Expr> kids;
01196
01197 int side = expr[0].isRational() ? 1 : 0;
01198
01199 vector<Expr> non_zero;
01200
01201 Expr::iterator i = expr[side].begin(), iend = expr[side].end();
01202 for (; i != iend; ++i) {
01203 Expr x = *i;
01204
01205 if (x.isRational()) {
01206 CHECK_SOUND(x.getRational() != 0, "multEqZero: once of the constants is 0");
01207 } else {
01208 Expr leaf = x;
01209 if (isPow(x)) {
01210
01211
01212
01213
01214
01215
01216
01217 leaf = x[1];
01218 }
01219 if (leaf >= rat(0))
01220 kids.push_back(leaf.eqExpr(rat(0)));
01221 else
01222 kids.push_back(rat(0).eqExpr(leaf));
01223 }
01224 }
01225 Expr newExpr;
01226 if (kids.size() == 1) newExpr = kids[0];
01227 else newExpr = Expr(OR, kids);
01228 if (withProof()) {
01229 pf = newPf("multEqZero", expr);
01230 }
01231
01232 return newRWTheorem(expr, newExpr, Assumptions::emptyAssump(), pf);
01233
01234 }
01235
01236
01237
01238
01239 Theorem ArithTheoremProducerOld::powEqZero(const Expr& expr)
01240 {
01241 if (CHECK_PROOFS) {
01242 CHECK_SOUND(expr.isEq() && expr[0].isRational() &&
01243 expr[0].getRational() == 0 &&
01244 isPow(expr[1]) && expr[1].arity() == 2 &&
01245 expr[1][0].isRational(),
01246 "powEqZero invariant violated"+expr.toString());
01247 }
01248 Proof pf;
01249 if (withProof()) {
01250 pf = newPf("powEqZero", expr);
01251 }
01252 Rational r = expr[1][0].getRational();
01253 Expr res;
01254 if (r <= 0) {
01255 res = d_em->falseExpr();
01256 }
01257 else {
01258 res = rat(0).eqExpr(expr[1][1]);
01259 }
01260 return newRWTheorem(expr, res, Assumptions::emptyAssump(), pf);
01261 }
01262
01263
01264
01265
01266 Theorem ArithTheoremProducerOld::elimPower(const Expr& expr)
01267 {
01268 Expr power1, power2;
01269 bool ok = d_theoryArith->isPowersEquality(expr, power1, power2);
01270 if (CHECK_PROOFS)
01271 CHECK_SOUND(ok, "elimPower invariant violated"+expr.toString());
01272 Proof pf;
01273 if (withProof())
01274 pf = newPf("elimPower", expr);
01275 Rational r = power1[0].getRational();
01276 Expr res = power1[1].eqExpr(power2[1]);
01277 if (r % 2 == 0)
01278 res = res.orExpr(power1[1].eqExpr(-power2[1]));
01279 return newRWTheorem(expr, res, Assumptions::emptyAssump(), pf);
01280 }
01281
01282
01283
01284
01285 Theorem ArithTheoremProducerOld::elimPowerConst(const Expr& expr, const Rational& root)
01286 {
01287 if (CHECK_PROOFS)
01288 CHECK_SOUND(expr.isEq(), "elimPowerConst invariant violated" + expr.toString());
01289 Rational constant;
01290 Expr power;
01291 bool ok = d_theoryArith->isPowerEquality(expr, constant, power);
01292 if (CHECK_PROOFS) {
01293 CHECK_SOUND(ok, "elimPowerConst invariant violated" + expr.toString());
01294 CHECK_SOUND(pow(power[0].getRational(), root) == constant, "elimPowerConst invariant violated" + expr.toString());
01295 }
01296
01297 Proof pf;
01298 if (withProof())
01299 pf = newPf("elimPowerConst", expr, rat(root));
01300 Rational r = power[0].getRational();
01301 Expr res = power[1].eqExpr(rat(root));
01302 if (r % 2 == 0)
01303 res = res.orExpr(power[1].eqExpr(rat(-root)));
01304
01305 return newRWTheorem(expr, res, Assumptions::emptyAssump(), pf);
01306 }
01307
01308
01309
01310 Theorem ArithTheoremProducerOld::evenPowerEqNegConst(const Expr& expr)
01311 {
01312 if (CHECK_PROOFS)
01313 CHECK_SOUND(expr.isEq(), "evenPowerEqNegConst, expecting equality, got " + expr.toString());
01314 Rational constant;
01315 Expr power;
01316 bool ok = d_theoryArith->isPowerEquality(expr, constant, power);
01317 if (CHECK_PROOFS) {
01318 CHECK_SOUND(ok, "evenPowerEqNegConst invariant violated" + expr.toString());
01319 CHECK_SOUND(constant < 0, "evenPowerEqNegConst invariant violated" + expr.toString());
01320 CHECK_SOUND(power[0].getRational().isInteger() && power[0].getRational() % 2 == 0, "evenPowerEqNegConst invariant violated" + expr.toString());
01321 }
01322 Proof pf;
01323 if (withProof())
01324 pf = newPf("evenPowerEqNegConst", expr);
01325 return newRWTheorem(expr, d_em->falseExpr(), Assumptions::emptyAssump(), pf);
01326 }
01327
01328
01329
01330 Theorem ArithTheoremProducerOld::intEqIrrational(const Expr& expr, const Theorem& isIntx)
01331 {
01332 if (CHECK_PROOFS)
01333 CHECK_SOUND(expr.isEq(), "intEqIrrational invariant violated" + expr.toString());
01334 Rational constant;
01335 Expr power;
01336 bool ok = d_theoryArith->isPowerEquality(expr, constant, power);
01337 if (CHECK_PROOFS) {
01338 CHECK_SOUND(ok, "intEqIrrational invariant violated" + expr.toString());
01339 CHECK_SOUND(constant != 0, "intEqIrrational invariant violated" + expr.toString());
01340 CHECK_SOUND(power[0].getRational() > 0, "intEqIrrational invariant violated" + expr.toString());
01341 CHECK_SOUND(ratRoot(constant, power[0].getRational().getUnsigned()) == 0, "intEqIrrational invariant violated" + expr.toString());
01342 CHECK_SOUND(isIntPred(isIntx.getExpr()) && isIntx.getExpr()[0] == expr[0], "intEqIrrational invariant violated" + isIntx.getExpr()[0].toString());
01343 }
01344
01345 const Assumptions& assump(isIntx.getAssumptionsRef());
01346 Proof pf;
01347 if (withProof())
01348 pf = newPf("int_eq_irr", expr, isIntx.getProof());
01349 return newRWTheorem(expr, d_em->falseExpr(), assump, pf);
01350 }
01351
01352
01353
01354
01355 Theorem ArithTheoremProducerOld::constPredicate(const Expr& e) {
01356 if(CHECK_PROOFS) {
01357 CHECK_SOUND(e.arity() == 2 && isRational(e[0]) && isRational(e[1]),
01358 CLASS_NAME "::constPredicate:\n "
01359 "non-const parameters: " + e.toString());
01360 }
01361 Proof pf;
01362 bool result(false);
01363 int kind = e.getKind();
01364 Rational r1 = e[0].getRational(), r2 = e[1].getRational();
01365 switch(kind) {
01366 case EQ:
01367 result = (r1 == r2)?true : false;
01368 break;
01369 case LT:
01370 result = (r1 < r2)?true : false;
01371 break;
01372 case LE:
01373 result = (r1 <= r2)?true : false;
01374 break;
01375 case GT:
01376 result = (r1 > r2)?true : false;
01377 break;
01378 case GE:
01379 result = (r1 >= r2)?true : false;
01380 break;
01381 default:
01382 if(CHECK_PROOFS) {
01383 CHECK_SOUND(false,
01384 "ArithTheoremProducerOld::constPredicate: wrong kind");
01385 }
01386 break;
01387 }
01388 Expr ret = (result) ? d_em->trueExpr() : d_em->falseExpr();
01389 if(withProof()) pf = newPf("const_predicate", e,ret);
01390 return newRWTheorem(e, ret, Assumptions::emptyAssump(), pf);
01391 }
01392
01393
01394 Theorem ArithTheoremProducerOld::rightMinusLeft(const Expr& e)
01395 {
01396 Proof pf;
01397 int kind = e.getKind();
01398 if(CHECK_PROOFS) {
01399 CHECK_SOUND((EQ==kind) ||
01400 (LT==kind) ||
01401 (LE==kind) ||
01402 (GE==kind) ||
01403 (GT==kind),
01404 "ArithTheoremProducerOld::rightMinusLeft: wrong kind");
01405 }
01406 if(withProof()) pf = newPf("right_minus_left",e);
01407 return newRWTheorem(e, Expr(e.getOp(), rat(0), e[1] - e[0]), Assumptions::emptyAssump(), pf);
01408 }
01409
01410
01411
01412 Theorem ArithTheoremProducerOld::leftMinusRight(const Expr& e)
01413 {
01414 Proof pf;
01415 int kind = e.getKind();
01416 if(CHECK_PROOFS) {
01417 CHECK_SOUND((EQ==kind) ||
01418 (LT==kind) ||
01419 (LE==kind) ||
01420 (GE==kind) ||
01421 (GT==kind),
01422 "ArithTheoremProducerOld::rightMinusLeft: wrong kind");
01423 }
01424 if(withProof()) pf = newPf("left_minus_right",e);
01425 return newRWTheorem(e, Expr(e.getOp(), e[0] - e[1], rat(0)), Assumptions::emptyAssump(), pf);
01426 }
01427
01428
01429
01430 Theorem ArithTheoremProducerOld::plusPredicate(const Expr& x,
01431 const Expr& y,
01432 const Expr& z, int kind) {
01433 if(CHECK_PROOFS) {
01434 CHECK_SOUND((EQ==kind) ||
01435 (LT==kind) ||
01436 (LE==kind) ||
01437 (GE==kind) ||
01438 (GT==kind),
01439 "ArithTheoremProducerOld::plusPredicate: wrong kind");
01440 }
01441 Proof pf;
01442 Expr left = Expr(kind, x, y);
01443 Expr right = Expr(kind, x + z, y + z);
01444 if(withProof()) pf = newPf("plus_predicate",left,right);
01445 return newRWTheorem(left, right, Assumptions::emptyAssump(), pf);
01446 }
01447
01448
01449 Theorem ArithTheoremProducerOld::multEqn(const Expr& x,
01450 const Expr& y,
01451 const Expr& z) {
01452 Proof pf;
01453 if(CHECK_PROOFS)
01454 CHECK_SOUND(z.isRational() && z.getRational() != 0,
01455 "ArithTheoremProducerOld::multEqn(): multiplying equation by 0");
01456 if(withProof()) pf = newPf("mult_eqn", x, y, z);
01457 return newRWTheorem(x.eqExpr(y), (x * z).eqExpr(y * z), Assumptions::emptyAssump(), pf);
01458 }
01459
01460
01461
01462 Theorem ArithTheoremProducerOld::divideEqnNonConst(const Expr& x,
01463 const Expr& y,
01464 const Expr& z) {
01465 Proof pf;
01466 if(withProof()) pf = newPf("mult_eqn_nonconst", x, y, z);
01467 return newRWTheorem(x.eqExpr(y), (z.eqExpr(rat(0))).orExpr((x / z).eqExpr(y / z)),
01468 Assumptions::emptyAssump(), pf);
01469 }
01470
01471
01472
01473
01474 Theorem ArithTheoremProducerOld::multIneqn(const Expr& e, const Expr& z)
01475 {
01476 int kind = e.getKind();
01477
01478 if(CHECK_PROOFS) {
01479 CHECK_SOUND((LT==kind) ||
01480 (LE==kind) ||
01481 (GE==kind) ||
01482 (GT==kind),
01483 "ArithTheoremProducerOld::multIneqn: wrong kind");
01484 CHECK_SOUND(z.isRational() && z.getRational() != 0,
01485 "ArithTheoremProducerOld::multIneqn: "
01486 "z must be non-zero rational: " + z.toString());
01487 }
01488 Op op(e.getOp());
01489 Proof pf;
01490
01491 Expr ret;
01492 if(0 < z.getRational())
01493 ret = Expr(op, e[0]*z, e[1]*z);
01494 else
01495 ret = Expr(op, e[1]*z, e[0]*z);
01496 if(withProof()) pf = newPf("mult_ineqn", e, ret);
01497 return newRWTheorem(e, ret, Assumptions::emptyAssump(), pf);
01498 }
01499
01500
01501
01502
01503
01504
01505
01506
01507
01508 Theorem ArithTheoremProducerOld::simpleIneqInt(const Expr& ineq, const Theorem& isIntRHS)
01509 {
01510
01511 Expr lhs = ineq[0];
01512 Expr rhs = ineq[1];
01513
01514
01515 int kind = ineq.getKind();
01516
01517
01518 if(CHECK_PROOFS) {
01519
01520 const Expr& isIntRHSExpr = isIntRHS.getExpr();
01521 CHECK_SOUND(isIntPred(isIntRHSExpr) && isIntRHSExpr[0] == rhs, "ArithTheoremProducerOld::multSimpleIneqnInt: not an integer proof of rhs");
01522
01523
01524 CHECK_SOUND((LT == kind) || (LE==kind) || (GE==kind) || (GT==kind), "ArithTheoremProducerOld::multSimpleIneqnInt: wrong kind");
01525
01526
01527 CHECK_SOUND(lhs.isRational() && lhs.getRational() == 0, "ArithTheoremProducerOld::multSimpleIneqnInt: left-hand side must be 0");
01528
01529
01530 CHECK_SOUND(isPlus(rhs), "ArithTheoremProducerOld::multSimpleIneqnInt: right-hand side must be a plus");
01531 CHECK_SOUND(rhs.arity() == 2, "ArithTheoremProducerOld::multSimpleIneqnInt: right-hand side a simple plus");
01532
01533 Expr a = rhs[0];
01534 Expr bx = rhs[1];
01535
01536
01537 CHECK_SOUND(a.isRational() && a.getRational().isInteger(), "ArithTheoremProducerOld::multSimpleIneqnInt: right-hand side a simple plus of a constant");
01538
01539
01540 CHECK_SOUND(isMult(bx) && bx.arity() == 2, "ArithTheoremProducerOld::multSimpleIneqnInt: right-hand side a simple plus of and a multiplication");
01541 Expr b = bx[0];
01542 Expr x = bx[1];
01543
01544
01545 CHECK_SOUND(b.isRational() && b.getRational().isInteger(), "ArithTheoremProducerOld::multSimpleIneqnInt: right-hand side a simple plus of and a multiplication of a constant");
01546
01547 CHECK_SOUND(x.isVar(), "ArithTheoremProducerOld::multSimpleIneqnInt: right-hand side a simple plus of and a multiplication of a constant and a leaf");
01548
01549
01550
01551 }
01552
01553 Proof pf;
01554 if(withProof()) {
01555 vector<Proof> pfs;
01556 pfs.push_back(isIntRHS.getProof());
01557 pf = newPf("simpleineqint", ineq, pf);
01558 }
01559
01560 Rational a = rhs[0].getRational();
01561 Rational b = rhs[1][0].getRational();
01562 Expr x = rhs[1][1];
01563
01564 Rational new_const;
01565 Expr ret;
01566 switch (kind) {
01567 case LT:
01568 if (b > 0) {
01569 new_const = floor(a/b);
01570 if (new_const != 0)
01571 ret = Expr(kind, rat(0), rat(new_const) + x);
01572 else
01573 ret = Expr(kind, rat(0), x);
01574 }
01575 else {
01576 new_const = ceil(a/b);
01577
01578 if (new_const != 0)
01579 ret = Expr(kind, rat(0), rat(-new_const) + rat(-1)*x);
01580 else
01581 ret = Expr(kind, rat(0), rat(-1)*x);
01582 }
01583 break;
01584 break;
01585 case LE:
01586 if (b > 0) {
01587 new_const = floor(a/b);
01588 if (new_const != 0)
01589 ret = Expr(kind, rat(0), rat(new_const) + x);
01590 else
01591 ret = Expr(kind, rat(0), x);
01592 }
01593 else {
01594 new_const = ceil(a/b);
01595
01596 if (new_const != 0)
01597 ret = Expr(kind, rat(0), rat(-new_const) + rat(-1)*x);
01598 else
01599 ret = Expr(kind, rat(0), rat(-1)*x);
01600 }
01601 break;
01602 case GE:
01603 case GT:
01604
01605 if (kind == GT) kind = LT;
01606 else kind = LE;
01607
01608 if (b > 0) {
01609 new_const = ceil(a/b);
01610
01611 if (new_const != 0)
01612 ret = Expr(kind, rat(0), rat(-new_const) + rat(-1)*x);
01613 else
01614 ret = Expr(kind, rat(0), rat(-1)*x);
01615 }
01616 else {
01617 new_const = floor(a/b);
01618 if (new_const != 0)
01619 ret = Expr(kind, rat(0), rat(new_const) + x);
01620 else
01621 ret = Expr(kind, rat(0), x);
01622 }
01623 break;
01624 }
01625
01626
01627 return newRWTheorem(ineq, ret, Assumptions::emptyAssump(), pf);
01628 }
01629
01630
01631 Theorem ArithTheoremProducerOld::eqToIneq(const Expr& e) {
01632
01633
01634 if (CHECK_PROOFS)
01635 CHECK_SOUND(e.isEq(), "eqToIneq: input must be an equality: " + e.toString());
01636
01637
01638 Proof pf;
01639
01640
01641 const Expr& x = e[0];
01642 const Expr& y = e[1];
01643
01644
01645 if (withProof())
01646 pf = newPf("eqToIneq", e);
01647
01648
01649 return newRWTheorem(e, leExpr(x,y).andExpr(geExpr(x,y)), Assumptions::emptyAssump(), pf);
01650 }
01651
01652
01653 Theorem ArithTheoremProducerOld::flipInequality(const Expr& e)
01654 {
01655 Proof pf;
01656 if(CHECK_PROOFS) {
01657 CHECK_SOUND(isGT(e) || isGE(e),
01658 "ArithTheoremProducerOld::flipInequality: wrong kind: " +
01659 e.toString());
01660 }
01661
01662 int kind = isGE(e) ? LE : LT;
01663 Expr ret = Expr(kind, e[1], e[0]);
01664 if(withProof()) pf = newPf("flip_inequality", e,ret);
01665 return newRWTheorem(e,ret, Assumptions::emptyAssump(), pf);
01666 }
01667
01668
01669
01670
01671
01672
01673 Theorem ArithTheoremProducerOld::negatedInequality(const Expr& e)
01674 {
01675 const Expr& ineq = e[0];
01676 if(CHECK_PROOFS) {
01677 CHECK_SOUND(e.isNot(),
01678 "ArithTheoremProducerOld::negatedInequality: wrong kind: " +
01679 e.toString());
01680 CHECK_SOUND(isIneq(ineq),
01681 "ArithTheoremProducerOld::negatedInequality: wrong kind: " +
01682 (ineq).toString());
01683 }
01684 Proof pf;
01685 if(withProof()) pf = newPf("negated_inequality", e);
01686
01687 int kind;
01688
01689
01690
01691
01692 kind =
01693 isLT(ineq) ? GE :
01694 isLE(ineq) ? GT :
01695 isGT(ineq) ? LE :
01696 LT;
01697 return newRWTheorem(e, Expr(kind, ineq[0], ineq[1]), Assumptions::emptyAssump(), pf);
01698 }
01699
01700
01701
01702 Theorem ArithTheoremProducerOld::realShadow(const Theorem& alphaLTt,
01703 const Theorem& tLTbeta)
01704 {
01705 const Expr& expr1 = alphaLTt.getExpr();
01706 const Expr& expr2 = tLTbeta.getExpr();
01707 if(CHECK_PROOFS) {
01708 CHECK_SOUND((isLE(expr1) || isLT(expr1)) &&
01709 (isLE(expr2) || isLT(expr2)),
01710 "ArithTheoremProducerOld::realShadow: Wrong Kind: " +
01711 alphaLTt.toString() + tLTbeta.toString());
01712
01713 CHECK_SOUND(expr1[1] == expr2[0],
01714 "ArithTheoremProducerOld::realShadow:"
01715 " t must be same for both inputs: " +
01716 expr1[1].toString() + " , " + expr2[0].toString());
01717 }
01718 Assumptions a(alphaLTt, tLTbeta);
01719 int firstKind = expr1.getKind();
01720 int secondKind = expr2.getKind();
01721 int kind = (firstKind == secondKind) ? firstKind : LT;
01722 Proof pf;
01723 if(withProof()) {
01724 vector<Proof> pfs;
01725 pfs.push_back(alphaLTt.getProof());
01726 pfs.push_back(tLTbeta.getProof());
01727 pf = newPf("real_shadow",expr1, expr2, pfs);
01728 }
01729 return newTheorem(Expr(kind, expr1[0], expr2[1]), a, pf);
01730 }
01731
01732
01733
01734
01735
01736
01737 Theorem ArithTheoremProducerOld::realShadowEq(const Theorem& alphaLEt,
01738 const Theorem& tLEalpha)
01739 {
01740 const Expr& expr1 = alphaLEt.getExpr();
01741 const Expr& expr2 = tLEalpha.getExpr();
01742 if(CHECK_PROOFS) {
01743 CHECK_SOUND(isLE(expr1) && isLE(expr2),
01744 "ArithTheoremProducerOld::realShadowLTLE: Wrong Kind: " +
01745 alphaLEt.toString() + tLEalpha.toString());
01746
01747 CHECK_SOUND(expr1[1] == expr2[0],
01748 "ArithTheoremProducerOld::realShadowLTLE:"
01749 " t must be same for both inputs: " +
01750 alphaLEt.toString() + " , " + tLEalpha.toString());
01751
01752 CHECK_SOUND(expr1[0] == expr2[1],
01753 "ArithTheoremProducerOld::realShadowLTLE:"
01754 " alpha must be same for both inputs: " +
01755 alphaLEt.toString() + " , " + tLEalpha.toString());
01756 }
01757 Assumptions a(alphaLEt, tLEalpha);
01758 Proof pf;
01759 if(withProof()) {
01760 vector<Proof> pfs;
01761 pfs.push_back(alphaLEt.getProof());
01762 pfs.push_back(tLEalpha.getProof());
01763 pf = newPf("real_shadow_eq", alphaLEt.getExpr(), tLEalpha.getExpr(), pfs);
01764 }
01765 return newRWTheorem(expr1[0], expr1[1], a, pf);
01766 }
01767
01768 Theorem
01769 ArithTheoremProducerOld::finiteInterval(const Theorem& aLEt,
01770 const Theorem& tLEac,
01771 const Theorem& isInta,
01772 const Theorem& isIntt) {
01773 const Expr& e1 = aLEt.getExpr();
01774 const Expr& e2 = tLEac.getExpr();
01775 if(CHECK_PROOFS) {
01776 CHECK_SOUND(isLE(e1) && isLE(e2),
01777 "ArithTheoremProducerOld::finiteInterval:\n e1 = "
01778 +e1.toString()+"\n e2 = "+e2.toString());
01779
01780 CHECK_SOUND(e1[1] == e2[0],
01781 "ArithTheoremProducerOld::finiteInterval:\n e1 = "
01782 +e1.toString()+"\n e2 = "+e2.toString());
01783
01784 CHECK_SOUND(isPlus(e2[1]) && e2[1].arity() == 2,
01785 "ArithTheoremProducerOld::finiteInterval:\n e1 = "
01786 +e1.toString()+"\n e2 = "+e2.toString());
01787
01788 CHECK_SOUND(e1[0] == e2[1][0],
01789 "ArithTheoremProducerOld::finiteInterval:\n e1 = "
01790 +e1.toString()+"\n e2 = "+e2.toString());
01791
01792 CHECK_SOUND(e2[1][1].isRational() && e2[1][1].getRational().isInteger()
01793 && e2[1][1].getRational() >= 1,
01794 "ArithTheoremProducerOld::finiteInterval:\n e1 = "
01795 +e1.toString()+"\n e2 = "+e2.toString());
01796
01797 const Expr& isIntaExpr = isInta.getExpr();
01798 const Expr& isInttExpr = isIntt.getExpr();
01799 CHECK_SOUND(isIntPred(isIntaExpr) && isIntaExpr[0] == e1[0],
01800 "Wrong integrality constraint:\n e1 = "
01801 +e1.toString()+"\n isInta = "+isIntaExpr.toString());
01802 CHECK_SOUND(isIntPred(isInttExpr) && isInttExpr[0] == e1[1],
01803 "Wrong integrality constraint:\n e1 = "
01804 +e1.toString()+"\n isIntt = "+isInttExpr.toString());
01805 }
01806 vector<Theorem> thms;
01807 thms.push_back(aLEt);
01808 thms.push_back(tLEac);
01809 thms.push_back(isInta);
01810 thms.push_back(isIntt);
01811 Assumptions a(thms);
01812 Proof pf;
01813 if(withProof()) {
01814 vector<Expr> es;
01815 vector<Proof> pfs;
01816 es.push_back(e1);
01817 es.push_back(e2);
01818 es.push_back(isInta.getExpr());
01819 es.push_back(isIntt.getExpr());
01820 pfs.push_back(aLEt.getProof());
01821 pfs.push_back(tLEac.getProof());
01822 pfs.push_back(isInta.getProof());
01823 pfs.push_back(isIntt.getProof());
01824 pf = newPf("finite_interval", es, pfs);
01825 }
01826
01827 Expr g(grayShadow(e1[1], e1[0], 0, e2[1][1].getRational()));
01828 return newTheorem(g, a, pf);
01829 }
01830
01831
01832
01833 Theorem ArithTheoremProducerOld::darkGrayShadow2ab(const Theorem& betaLEbx,
01834 const Theorem& axLEalpha,
01835 const Theorem& isIntAlpha,
01836 const Theorem& isIntBeta,
01837 const Theorem& isIntx) {
01838 const Expr& expr1 = betaLEbx.getExpr();
01839 const Expr& expr2 = axLEalpha.getExpr();
01840 const Expr& isIntAlphaExpr = isIntAlpha.getExpr();
01841 const Expr& isIntBetaExpr = isIntBeta.getExpr();
01842 const Expr& isIntxExpr = isIntx.getExpr();
01843
01844 if(CHECK_PROOFS) {
01845 CHECK_SOUND(isLE(expr1) && isLE(expr2),
01846 "ArithTheoremProducerOld::darkGrayShadow2ab: Wrong Kind: " +
01847 betaLEbx.toString() + axLEalpha.toString());
01848 }
01849
01850 const Expr& beta = expr1[0];
01851 const Expr& bx = expr1[1];
01852 const Expr& ax = expr2[0];
01853 const Expr& alpha = expr2[1];
01854 Expr a_expr, b_expr, x;
01855 d_theoryArith->separateMonomial(ax, a_expr, x);
01856 d_theoryArith->separateMonomial(bx, b_expr, x);
01857 Rational a = a_expr.getRational();
01858 Rational b = b_expr.getRational();
01859
01860 if(CHECK_PROOFS) {
01861
01862 CHECK_SOUND(isIntPred(isIntAlphaExpr) && isIntAlphaExpr[0] == alpha,
01863 "ArithTheoremProducerOld::darkGrayShadow2ab:\n "
01864 "wrong integrality constraint:\n alpha = "
01865 +alpha.toString()+"\n isIntAlpha = "
01866 +isIntAlphaExpr.toString());
01867 CHECK_SOUND(isIntPred(isIntBetaExpr) && isIntBetaExpr[0] == beta,
01868 "ArithTheoremProducerOld::darkGrayShadow2ab:\n "
01869 "wrong integrality constraint:\n beta = "
01870 +beta.toString()+"\n isIntBeta = "
01871 +isIntBetaExpr.toString());
01872 CHECK_SOUND(isIntPred(isIntxExpr) && isIntxExpr[0] == x,
01873 "ArithTheoremProducerOld::darkGrayShadow2ab:\n "
01874 "wrong integrality constraint:\n x = "
01875 +x.toString()+"\n isIntx = "
01876 +isIntxExpr.toString());
01877
01878
01879
01880
01881
01882
01883
01884
01885 CHECK_SOUND(1 <= a && a <= b && 2 <= b,
01886 "ArithTheoremProducerOld::darkGrayShadow2ab:\n beta<=bx: "
01887 +betaLEbx.toString()
01888 +"\n ax<=alpha: "+ axLEalpha.toString());
01889 }
01890 vector<Theorem> thms;
01891 thms.push_back(betaLEbx);
01892 thms.push_back(axLEalpha);
01893 thms.push_back(isIntAlpha);
01894 thms.push_back(isIntBeta);
01895 thms.push_back(isIntx);
01896 Assumptions A(thms);
01897
01898 Expr bAlpha = multExpr(rat(b), alpha);
01899 Expr aBeta = multExpr(rat(a), beta);
01900 Expr t = minusExpr(bAlpha, aBeta);
01901 Expr d = geExpr(t, rat(a*b-1));
01902 Expr g = grayShadow(ax, alpha, -a+1, 0);
01903
01904 Proof pf;
01905 if(withProof()) {
01906 vector<Expr> exprs;
01907 exprs.push_back(expr1);
01908 exprs.push_back(expr2);
01909 exprs.push_back(d);
01910 exprs.push_back(g);
01911
01912 vector<Proof> pfs;
01913 pfs.push_back(betaLEbx.getProof());
01914 pfs.push_back(axLEalpha.getProof());
01915 pfs.push_back(isIntAlpha.getProof());
01916 pfs.push_back(isIntBeta.getProof());
01917 pfs.push_back(isIntx.getProof());
01918
01919 pf = newPf("dark_grayshadow_2ab", exprs, pfs);
01920 }
01921
01922 return newTheorem((d || g), A, pf);
01923 }
01924
01925
01926 Theorem ArithTheoremProducerOld::darkGrayShadow2ba(const Theorem& betaLEbx,
01927 const Theorem& axLEalpha,
01928 const Theorem& isIntAlpha,
01929 const Theorem& isIntBeta,
01930 const Theorem& isIntx) {
01931 const Expr& expr1 = betaLEbx.getExpr();
01932 const Expr& expr2 = axLEalpha.getExpr();
01933 const Expr& isIntAlphaExpr = isIntAlpha.getExpr();
01934 const Expr& isIntBetaExpr = isIntBeta.getExpr();
01935 const Expr& isIntxExpr = isIntx.getExpr();
01936
01937 if(CHECK_PROOFS) {
01938 CHECK_SOUND(isLE(expr1) && isLE(expr2),
01939 "ArithTheoremProducerOld::darkGrayShadow2ba: Wrong Kind: " +
01940 betaLEbx.toString() + axLEalpha.toString());
01941 }
01942
01943 const Expr& beta = expr1[0];
01944 const Expr& bx = expr1[1];
01945 const Expr& ax = expr2[0];
01946 const Expr& alpha = expr2[1];
01947
01948 Expr a_expr, b_expr, x;
01949 d_theoryArith->separateMonomial(ax, a_expr, x);
01950 d_theoryArith->separateMonomial(bx, b_expr, x);
01951 Rational a = a_expr.getRational();
01952 Rational b = b_expr.getRational();
01953
01954 if(CHECK_PROOFS) {
01955
01956 CHECK_SOUND(isIntPred(isIntAlphaExpr) && isIntAlphaExpr[0] == alpha,
01957 "ArithTheoremProducerOld::darkGrayShadow2ab:\n "
01958 "wrong integrality constraint:\n alpha = "
01959 +alpha.toString()+"\n isIntAlpha = "
01960 +isIntAlphaExpr.toString());
01961 CHECK_SOUND(isIntPred(isIntBetaExpr) && isIntBetaExpr[0] == beta,
01962 "ArithTheoremProducerOld::darkGrayShadow2ab:\n "
01963 "wrong integrality constraint:\n beta = "
01964 +beta.toString()+"\n isIntBeta = "
01965 +isIntBetaExpr.toString());
01966 CHECK_SOUND(isIntPred(isIntxExpr) && isIntxExpr[0] == x,
01967 "ArithTheoremProducerOld::darkGrayShadow2ab:\n "
01968 "wrong integrality constraint:\n x = "
01969 +x.toString()+"\n isIntx = "
01970 +isIntxExpr.toString());
01971
01972
01973
01974
01975
01976
01977
01978
01979 CHECK_SOUND(1 <= b && b <= a && 2 <= a,
01980 "ArithTheoremProducerOld::darkGrayShadow2ba:\n beta<=bx: "
01981 +betaLEbx.toString()
01982 +"\n ax<=alpha: "+ axLEalpha.toString());
01983 }
01984 vector<Theorem> thms;
01985 thms.push_back(betaLEbx);
01986 thms.push_back(axLEalpha);
01987 thms.push_back(isIntAlpha);
01988 thms.push_back(isIntBeta);
01989 thms.push_back(isIntx);
01990 Assumptions A(thms);
01991 Proof pf;
01992 if(withProof()) {
01993 vector<Proof> pfs;
01994 pfs.push_back(betaLEbx.getProof());
01995 pfs.push_back(axLEalpha.getProof());
01996 pfs.push_back(isIntAlpha.getProof());
01997 pfs.push_back(isIntBeta.getProof());
01998 pfs.push_back(isIntx.getProof());
01999
02000 pf = newPf("dark_grayshadow_2ba", betaLEbx.getExpr(),
02001 axLEalpha.getExpr(), pfs);
02002 }
02003
02004 Expr bAlpha = multExpr(rat(b), alpha);
02005 Expr aBeta = multExpr(rat(a), beta);
02006 Expr t = minusExpr(bAlpha, aBeta);
02007 Expr d = geExpr(t, rat(a*b-1));
02008 Expr g = grayShadow(bx, beta, 0, b-1);
02009 return newTheorem((d || g), A, pf);
02010 }
02011
02012
02013
02014 Theorem ArithTheoremProducerOld::expandDarkShadow(const Theorem& darkShadow) {
02015 const Expr& theShadow = darkShadow.getExpr();
02016 if(CHECK_PROOFS){
02017 CHECK_SOUND(isDarkShadow(theShadow),
02018 "ArithTheoremProducerOld::expandDarkShadow: not DARK_SHADOW: " +
02019 theShadow.toString());
02020 }
02021 Proof pf;
02022 if(withProof())
02023 pf = newPf("expand_dark_shadow", theShadow, darkShadow.getProof());
02024 return newTheorem(leExpr(theShadow[0], theShadow[1]), darkShadow.getAssumptionsRef(), pf);
02025 }
02026
02027
02028
02029 Theorem ArithTheoremProducerOld::expandGrayShadow0(const Theorem& grayShadow) {
02030 const Expr& theShadow = grayShadow.getExpr();
02031 if(CHECK_PROOFS) {
02032 CHECK_SOUND(isGrayShadow(theShadow),
02033 "ArithTheoremProducerOld::expandGrayShadowConst0:"
02034 " not GRAY_SHADOW: " +
02035 theShadow.toString());
02036 CHECK_SOUND(theShadow[2] == theShadow[3],
02037 "ArithTheoremProducerOld::expandGrayShadow0: c1!=c2: " +
02038 theShadow.toString());
02039 }
02040 Proof pf;
02041 if(withProof()) pf = newPf("expand_gray_shadowconst0", theShadow,
02042 grayShadow.getProof());
02043 const Expr& v = theShadow[0];
02044 const Expr& e = theShadow[1];
02045 return newRWTheorem(v, e + theShadow[2], grayShadow.getAssumptionsRef(), pf);
02046 }
02047
02048
02049
02050
02051
02052
02053
02054 Theorem ArithTheoremProducerOld::splitGrayShadow(const Theorem& gThm) {
02055 const Expr& theShadow = gThm.getExpr();
02056 if(CHECK_PROOFS) {
02057 CHECK_SOUND(isGrayShadow(theShadow),
02058 "ArithTheoremProducerOld::expandGrayShadowConst: not a shadow" +
02059 theShadow.toString());
02060 }
02061
02062 const Rational& c1 = theShadow[2].getRational();
02063 const Rational& c2 = theShadow[3].getRational();
02064
02065 if(CHECK_PROOFS) {
02066 CHECK_SOUND(c1.isInteger() && c2.isInteger() && c1 < c2,
02067 "ArithTheoremProducerOld::expandGrayShadow: " +
02068 theShadow.toString());
02069 }
02070
02071 const Expr& v = theShadow[0];
02072 const Expr& e = theShadow[1];
02073
02074 Proof pf;
02075 Rational c(floor((c1+c2) / 2));
02076 Expr g1(grayShadow(v, e, c1, c));
02077 Expr g2(grayShadow(v, e, c+1, c2));
02078
02079 if(withProof()){
02080 vector<Expr> exprs;
02081 exprs.push_back(theShadow);
02082 exprs.push_back(g1);
02083 exprs.push_back(g2);
02084 pf = newPf("split_gray_shadow", exprs, gThm.getProof());
02085 }
02086
02087 return newTheorem((g1 || g2) && (!g1 || !g2), gThm.getAssumptionsRef(), pf);
02088 }
02089
02090
02091 Theorem ArithTheoremProducerOld::expandGrayShadow(const Theorem& gThm) {
02092 const Expr& theShadow = gThm.getExpr();
02093 if(CHECK_PROOFS) {
02094 CHECK_SOUND(isGrayShadow(theShadow),
02095 "ArithTheoremProducerOld::expandGrayShadowConst: not a shadow" +
02096 theShadow.toString());
02097 }
02098
02099 const Rational& c1 = theShadow[2].getRational();
02100 const Rational& c2 = theShadow[3].getRational();
02101
02102 if(CHECK_PROOFS) {
02103 CHECK_SOUND(c1.isInteger() && c2.isInteger() && c1 < c2,
02104 "ArithTheoremProducerOld::expandGrayShadow: " +
02105 theShadow.toString());
02106 }
02107
02108 const Expr& v = theShadow[0];
02109 const Expr& e = theShadow[1];
02110
02111 Proof pf;
02112 if(withProof())
02113 pf = newPf("expand_gray_shadow", theShadow, gThm.getProof());
02114 Expr ineq1(leExpr(e+rat(c1), v));
02115 Expr ineq2(leExpr(v, e+rat(c2)));
02116 return newTheorem(ineq1 && ineq2, gThm.getAssumptionsRef(), pf);
02117 }
02118
02119
02120
02121 Theorem
02122 ArithTheoremProducerOld::expandGrayShadowConst(const Theorem& gThm) {
02123 const Expr& theShadow = gThm.getExpr();
02124 const Expr& ax = theShadow[0];
02125 const Expr& cExpr = theShadow[1];
02126 const Expr& bExpr = theShadow[2];
02127
02128 if(CHECK_PROOFS) {
02129 CHECK_SOUND(!isMult(ax) || ax[0].isRational(),
02130 "ArithTheoremProducerOld::expandGrayShadowConst: "
02131 "'a' in a*x is not a const: " +theShadow.toString());
02132 }
02133
02134 Rational a = isMult(ax)? ax[0].getRational() : 1;
02135
02136 if(CHECK_PROOFS) {
02137 CHECK_SOUND(isGrayShadow(theShadow),
02138 "ArithTheoremProducerOld::expandGrayShadowConst: "
02139 "not a GRAY_SHADOW: " +theShadow.toString());
02140 CHECK_SOUND(a.isInteger() && a >= 1,
02141 "ArithTheoremProducerOld::expandGrayShadowConst: "
02142 "'a' is not integer: " +theShadow.toString());
02143 CHECK_SOUND(cExpr.isRational(),
02144 "ArithTheoremProducerOld::expandGrayShadowConst: "
02145 "'c' is not rational" +theShadow.toString());
02146 CHECK_SOUND(bExpr.isRational() && bExpr.getRational().isInteger(),
02147 "ArithTheoremProducerOld::expandGrayShadowConst: b not integer: "
02148 +theShadow.toString());
02149 }
02150
02151 const Rational& b = bExpr.getRational();
02152 const Rational& c = cExpr.getRational();
02153 Rational j = constRHSGrayShadow(c,b,a);
02154
02155 Rational signB = (b>0)? 1 : -1;
02156
02157 Rational bAbs = abs(b);
02158
02159 const Assumptions& assump(gThm.getAssumptionsRef());
02160 Proof pf;
02161 Theorem conc;
02162
02163 if(bAbs < j) {
02164 if(withProof())
02165 pf = newPf("expand_gray_shadow_const_0", theShadow,
02166 gThm.getProof());
02167 conc = newTheorem(d_em->falseExpr(), assump, pf);
02168 } else if(bAbs < a+j) {
02169 if(withProof())
02170 pf = newPf("expand_gray_shadow_const_1", theShadow,
02171 gThm.getProof());
02172 conc = newRWTheorem(ax, rat(c+b-signB*j), assump, pf);
02173 } else {
02174 if(withProof())
02175 pf = newPf("expand_gray_shadow_const", theShadow,
02176 gThm.getProof());
02177 Expr newGrayShadow(Expr(GRAY_SHADOW, ax, cExpr, rat(b-signB*(a+j))));
02178 conc = newTheorem(ax.eqExpr(rat(c+b-signB*j)).orExpr(newGrayShadow),
02179 assump, pf);
02180 }
02181
02182 return conc;
02183 }
02184
02185
02186 Theorem
02187 ArithTheoremProducerOld::grayShadowConst(const Theorem& gThm) {
02188 const Expr& g = gThm.getExpr();
02189 bool checkProofs(CHECK_PROOFS);
02190 if(checkProofs) {
02191 CHECK_SOUND(isGrayShadow(g), "ArithTheoremProducerOld::grayShadowConst("
02192 +g.toString()+")");
02193 }
02194
02195 const Expr& ax = g[0];
02196 const Expr& e = g[1];
02197 const Rational& c1 = g[2].getRational();
02198 const Rational& c2 = g[3].getRational();
02199 Expr aExpr, x;
02200 d_theoryArith->separateMonomial(ax, aExpr, x);
02201
02202 if(checkProofs) {
02203 CHECK_SOUND(e.isRational() && e.getRational().isInteger(),
02204 "ArithTheoremProducerOld::grayShadowConst("+g.toString()+")");
02205 CHECK_SOUND(aExpr.isRational(),
02206 "ArithTheoremProducerOld::grayShadowConst("+g.toString()+")");
02207 }
02208
02209 const Rational& a = aExpr.getRational();
02210 const Rational& c = e.getRational();
02211
02212 if(checkProofs) {
02213 CHECK_SOUND(a.isInteger() && a >= 2,
02214 "ArithTheoremProducerOld::grayShadowConst("+g.toString()+")");
02215 }
02216
02217 Rational newC1 = ceil((c1+c)/a), newC2 = floor((c2+c)/a);
02218 Expr newG((newC1 > newC2)? d_em->falseExpr()
02219 : grayShadow(x, rat(0), newC1, newC2));
02220 Proof pf;
02221 if(withProof())
02222 pf = newPf("gray_shadow_const", g, newG, gThm.getProof());
02223 return newTheorem(newG, gThm.getAssumptionsRef(), pf);
02224 }
02225
02226
02227 Rational ArithTheoremProducerOld::constRHSGrayShadow(const Rational& c,
02228 const Rational& b,
02229 const Rational& a) {
02230 DebugAssert(c.isInteger() &&
02231 b.isInteger() &&
02232 a.isInteger() &&
02233 b != 0,
02234 "ArithTheoremProducerOld::constRHSGrayShadow: a, b, c must be ints");
02235 if (b > 0)
02236 return mod(c+b, a);
02237 else
02238 return mod(a-(c+b), a);
02239 }
02240
02241
02242
02243
02244
02245 Theorem ArithTheoremProducerOld::lessThanToLE(const Theorem& less,
02246 const Theorem& isIntLHS,
02247 const Theorem& isIntRHS,
02248 bool changeRight) {
02249 const Expr& ineq = less.getExpr();
02250 const Expr& isIntLHSexpr = isIntLHS.getExpr();
02251 const Expr& isIntRHSexpr = isIntRHS.getExpr();
02252
02253 if(CHECK_PROOFS) {
02254 CHECK_SOUND(isLT(ineq),
02255 "ArithTheoremProducerOld::LTtoLE: ineq must be <");
02256
02257 CHECK_SOUND(isIntPred(isIntLHSexpr) && isIntLHSexpr[0] == ineq[0],
02258 "ArithTheoremProducerOld::lessThanToLE: bad integrality check:\n"
02259 " ineq = "+ineq.toString()+"\n isIntLHS = "
02260 +isIntLHSexpr.toString());
02261 CHECK_SOUND(isIntPred(isIntRHSexpr) && isIntRHSexpr[0] == ineq[1],
02262 "ArithTheoremProducerOld::lessThanToLE: bad integrality check:\n"
02263 " ineq = "+ineq.toString()+"\n isIntRHS = "
02264 +isIntRHSexpr.toString());
02265 }
02266 vector<Theorem> thms;
02267 thms.push_back(less);
02268 thms.push_back(isIntLHS);
02269 thms.push_back(isIntRHS);
02270 Assumptions a(thms);
02271 Proof pf;
02272 Expr le = changeRight?
02273 leExpr(ineq[0], ineq[1] + rat(-1))
02274 : leExpr(ineq[0] + rat(1), ineq[1]);
02275 if(withProof()) {
02276 vector<Proof> pfs;
02277 pfs.push_back(less.getProof());
02278 pfs.push_back(isIntLHS.getProof());
02279 pfs.push_back(isIntRHS.getProof());
02280 pf = newPf(changeRight? "lessThan_To_LE_rhs" : "lessThan_To_LE_lhs",
02281 ineq,le, pfs);
02282 }
02283
02284 return newRWTheorem(ineq, le, a, pf);
02285 }
02286
02287
02288
02289
02290
02291
02292
02293
02294
02295
02296 Theorem
02297 ArithTheoremProducerOld::intVarEqnConst(const Expr& eqn,
02298 const Theorem& isIntx) {
02299 const Expr& left(eqn[0]);
02300 const Expr& right(eqn[1]);
02301 const Expr& isIntxexpr(isIntx.getExpr());
02302
02303 if(CHECK_PROOFS) {
02304 CHECK_SOUND((isMult(right) && right[0].isRational())
02305 || (right.arity() == 2 && isPlus(right)
02306 && right[0].isRational()
02307 && ((!isMult(right[1]) || right[1][0].isRational()))),
02308 "ArithTheoremProducerOld::intVarEqnConst: "
02309 "rhs has a wrong format: " + right.toString());
02310 CHECK_SOUND(left.isRational() && 0 == left.getRational(),
02311 "ArithTheoremProducerOld:intVarEqnConst:left is not a zero: " +
02312 left.toString());
02313 }
02314
02315 Expr x(right);
02316 Rational a(1), c(0);
02317 if(isMult(right)) {
02318 Expr aExpr;
02319 d_theoryArith->separateMonomial(right, aExpr, x);
02320 a = aExpr.getRational();
02321 } else {
02322 c = right[0].getRational();
02323 Expr aExpr;
02324 d_theoryArith->separateMonomial(right[1], aExpr, x);
02325 a = aExpr.getRational();
02326 }
02327 if(CHECK_PROOFS) {
02328 CHECK_SOUND(isIntPred(isIntxexpr) && isIntxexpr[0] == x,
02329 "ArithTheoremProducerOld:intVarEqnConst: "
02330 "bad integrality constraint:\n right = " +
02331 right.toString()+"\n isIntx = "+isIntxexpr.toString());
02332 CHECK_SOUND(a!=0, "ArithTheoremProducerOld:intVarEqnConst: eqn = "
02333 +eqn.toString());
02334 }
02335 const Assumptions& assump(isIntx.getAssumptionsRef());
02336
02337
02338
02339
02340
02341
02342
02343
02344
02345
02346
02347
02348
02349
02350
02351 Proof pf;
02352
02353 Rational r(-c/a);
02354
02355 if(r.isInteger()){
02356 if(withProof())
02357 pf = newPf("int_const_eq", eqn, x.eqExpr(rat(r)),isIntx.getProof());
02358 return newRWTheorem(eqn, x.eqExpr(rat(r)), assump, pf);
02359 }
02360 else{
02361 if(withProof())
02362 pf = newPf("int_const_eq", eqn, d_em->falseExpr(),isIntx.getProof());
02363 return newRWTheorem(eqn, d_em->falseExpr(), assump, pf);
02364 }
02365 }
02366
02367
02368 Expr
02369 ArithTheoremProducerOld::create_t(const Expr& eqn) {
02370 const Expr& lhs = eqn[0];
02371 DebugAssert(isMult(lhs),
02372 CLASS_NAME "create_t : lhs must be a MULT"
02373 + lhs.toString());
02374 const Expr& x = lhs[1];
02375 Rational m = lhs[0].getRational()+1;
02376 DebugAssert(m > 0, "ArithTheoremProducerOld::create_t: m = "+m.toString());
02377 vector<Expr> kids;
02378 if(isPlus(eqn[1]))
02379 sumModM(kids, eqn[1], m, m);
02380 else
02381 kids.push_back(monomialModM(eqn[1], m, m));
02382
02383 kids.push_back(multExpr(rat(1/m), x));
02384 return plusExpr(kids);
02385 }
02386
02387 Expr
02388 ArithTheoremProducerOld::create_t2(const Expr& lhs, const Expr& rhs,
02389 const Expr& sigma) {
02390 Rational m = lhs[0].getRational()+1;
02391 DebugAssert(m > 0, "ArithTheoremProducerOld::create_t2: m = "+m.toString());
02392 vector<Expr> kids;
02393 if(isPlus(rhs))
02394 sumModM(kids, rhs, m, -1);
02395 else {
02396 kids.push_back(rat(0));
02397 Expr monom = monomialModM(rhs, m, -1);
02398 if(!monom.isRational())
02399 kids.push_back(monom);
02400 else
02401 DebugAssert(monom.getRational() == 0, "");
02402 }
02403 kids.push_back(rat(m)*sigma);
02404 return plusExpr(kids);
02405 }
02406
02407 Expr
02408 ArithTheoremProducerOld::create_t3(const Expr& lhs, const Expr& rhs,
02409 const Expr& sigma) {
02410 const Rational& a = lhs[0].getRational();
02411 Rational m = a+1;
02412 DebugAssert(m > 0, "ArithTheoremProducerOld::create_t3: m = "+m.toString());
02413 vector<Expr> kids;
02414 if(isPlus(rhs))
02415 sumMulF(kids, rhs, m, 1);
02416 else {
02417 kids.push_back(rat(0));
02418 Expr monom = monomialMulF(rhs, m, 1);
02419 if(!monom.isRational())
02420 kids.push_back(monom);
02421 else
02422 DebugAssert(monom.getRational() == 0, "");
02423 }
02424 kids.push_back(rat(-a)*sigma);
02425 return plusExpr(kids);
02426 }
02427
02428 Rational
02429 ArithTheoremProducerOld::modEq(const Rational& i, const Rational& m) {
02430 DebugAssert(m > 0, "ArithTheoremProducerOld::modEq: m = "+m.toString());
02431 Rational half(1,2);
02432 Rational res((i - m*(floor((i/m) + half))));
02433 TRACE("arith eq", "modEq("+i.toString()+", "+m.toString()+") = ", res, "");
02434 return res;
02435 }
02436
02437 Rational
02438 ArithTheoremProducerOld::f(const Rational& i, const Rational& m) {
02439 DebugAssert(m > 0, "ArithTheoremProducerOld::f: m = "+m.toString());
02440 Rational half(1,2);
02441 return (floor(i/m + half)+modEq(i,m));
02442 }
02443
02444 void
02445 ArithTheoremProducerOld::sumModM(vector<Expr>& summands, const Expr& sum,
02446 const Rational& m, const Rational& divisor) {
02447 DebugAssert(divisor != 0, "ArithTheoremProducerOld::sumModM: divisor = "
02448 +divisor.toString());
02449 Expr::iterator i = sum.begin();
02450 DebugAssert(i != sum.end(), CLASS_NAME "::sumModM");
02451 Rational C = i->getRational();
02452 C = modEq(C,m)/divisor;
02453 summands.push_back(rat(C));
02454 i++;
02455 for(Expr::iterator iend=sum.end(); i!=iend; ++i) {
02456 Expr monom = monomialModM(*i, m, divisor);
02457 if(!monom.isRational())
02458 summands.push_back(monom);
02459 else
02460 DebugAssert(monom.getRational() == 0, "");
02461 }
02462 }
02463
02464 Expr
02465 ArithTheoremProducerOld::monomialModM(const Expr& i,
02466 const Rational& m, const Rational& divisor)
02467 {
02468 DebugAssert(divisor != 0, "ArithTheoremProducerOld::monomialModM: divisor = "
02469 +divisor.toString());
02470 Expr res;
02471 if(isMult(i)) {
02472 Rational ai = i[0].getRational();
02473 ai = modEq(ai,m)/divisor;
02474 if(0 == ai) res = rat(0);
02475 else if(1 == ai && i.arity() == 2) res = i[1];
02476 else {
02477 vector<Expr> kids = i.getKids();
02478 kids[0] = rat(ai);
02479 res = multExpr(kids);
02480 }
02481 } else {
02482 Rational ai = modEq(1,m)/divisor;
02483 if(1 == ai) res = i;
02484 else res = rat(ai)*i;
02485 }
02486 DebugAssert(!res.isNull(), "ArithTheoremProducerOld::monomialModM()");
02487 TRACE("arith eq", "monomialModM(i="+i.toString()+", m="+m.toString()
02488 +", div="+divisor.toString()+") = ", res, "");
02489 return res;
02490 }
02491
02492 void
02493 ArithTheoremProducerOld::sumMulF(vector<Expr>& summands, const Expr& sum,
02494 const Rational& m, const Rational& divisor) {
02495 DebugAssert(divisor != 0, "ArithTheoremProducerOld::sumMulF: divisor = "
02496 +divisor.toString());
02497 Expr::iterator i = sum.begin();
02498 DebugAssert(i != sum.end(), CLASS_NAME "::sumModM");
02499 Rational C = i->getRational();
02500 C = f(C,m)/divisor;
02501 summands.push_back(rat(C));
02502 i++;
02503 for(Expr::iterator iend=sum.end(); i!=iend; ++i) {
02504 Expr monom = monomialMulF(*i, m, divisor);
02505 if(!monom.isRational())
02506 summands.push_back(monom);
02507 else
02508 DebugAssert(monom.getRational() == 0, "");
02509 }
02510 }
02511
02512 Expr
02513 ArithTheoremProducerOld::monomialMulF(const Expr& i,
02514 const Rational& m, const Rational& divisor)
02515 {
02516 DebugAssert(divisor != 0, "ArithTheoremProducerOld::monomialMulF: divisor = "
02517 +divisor.toString());
02518 Rational ai = isMult(i) ? (i)[0].getRational() : 1;
02519 Expr xi = isMult(i) ? (i)[1] : (i);
02520 ai = f(ai,m)/divisor;
02521 if(0 == ai) return rat(0);
02522 if(1 == ai) return xi;
02523 return multExpr(rat(ai), xi);
02524 }
02525
02526
02527
02528
02529 Expr
02530 ArithTheoremProducerOld::substitute(const Expr& term, ExprMap<Expr>& eMap)
02531 {
02532 ExprMap<Expr>::iterator i, iend = eMap.end();
02533
02534 i = eMap.find(term);
02535 if(iend != i)
02536 return (*i).second;
02537
02538 if (isMult(term)) {
02539
02540 i = eMap.find(term[1]);
02541 if(iend != i)
02542 return term[0]*(*i).second;
02543 else
02544 return term;
02545 }
02546
02547 if(isPlus(term)) {
02548 vector<Expr> output;
02549 for(Expr::iterator j = term.begin(), jend = term.end(); j != jend; ++j)
02550 output.push_back(substitute(*j, eMap));
02551 return plusExpr(output);
02552 }
02553 return term;
02554 }
02555
02556 bool ArithTheoremProducerOld::greaterthan(const Expr & l, const Expr & r)
02557 {
02558
02559 if (l==r) return false;
02560
02561 switch(l.getKind()) {
02562 case RATIONAL_EXPR:
02563 DebugAssert(!r.isRational(), "");
02564 return true;
02565 break;
02566 case POW:
02567 switch (r.getKind()) {
02568 case RATIONAL_EXPR:
02569
02570
02571 return false;
02572 break;
02573 case POW:
02574
02575
02576 return
02577 ((r[1] < l[1]) ||
02578 ((r[1]==l[1]) && (r[0].getRational() < l[0].getRational())));
02579 break;
02580
02581 case MULT:
02582 DebugAssert(r.arity() > 1, "");
02583 DebugAssert((r.arity() > 2) || (r[1] != l), "");
02584 if (r[1] == l) return false;
02585 return greaterthan(l, r[1]);
02586 break;
02587 case PLUS:
02588 DebugAssert(false, "");
02589 return true;
02590 break;
02591 default:
02592
02593 return ((r < l[1]) || ((r == l[1]) && l[0].getRational() > 1));
02594 break;
02595 }
02596 break;
02597 case MULT:
02598 DebugAssert(l.arity() > 1, "");
02599 switch (r.getKind()) {
02600 case RATIONAL_EXPR:
02601 return false;
02602 break;
02603 case POW:
02604 DebugAssert(l.arity() > 1, "");
02605 DebugAssert((l.arity() > 2) || (l[1] != r), "");
02606
02607
02608 return ((l[1] == r) || greaterthan(l[1], r));
02609 break;
02610 case MULT:
02611 {
02612
02613 DebugAssert(r.arity() > 1, "");
02614 Expr::iterator i = l.begin();
02615 Expr::iterator j = r.begin();
02616 ++i;
02617 ++j;
02618 for (; i != l.end() && j != r.end(); ++i, ++j) {
02619 if (*i == *j)
02620 continue;
02621 return greaterthan(*i,*j);
02622 }
02623 DebugAssert(i != l.end() || j != r.end(), "");
02624 if (i == l.end()) {
02625
02626 return false;
02627 }
02628 else
02629 {
02630
02631 return true;
02632 }
02633 }
02634 break;
02635 case PLUS:
02636 DebugAssert(false, "");
02637 return true;
02638 break;
02639 default:
02640
02641 DebugAssert((l.arity() > 2) || (l[1] != r), "");
02642 return ((l[1] == r) || greaterthan(l[1], r));
02643 break;
02644 }
02645 break;
02646 case PLUS:
02647 DebugAssert(false, "");
02648 return true;
02649 break;
02650 default:
02651
02652 switch (r.getKind()) {
02653 case RATIONAL_EXPR:
02654 return false;
02655 break;
02656 case POW:
02657 return ((r[1] < l) || ((r[1] == l) && (r[0].getRational() < 1)));
02658 break;
02659 case MULT:
02660 DebugAssert(r.arity() > 1, "");
02661 DebugAssert((r.arity() > 2) || (r[1] != l), "");
02662 if (l == r[1]) return false;
02663 return greaterthan(l,r[1]);
02664 break;
02665 case PLUS:
02666 DebugAssert(false, "");
02667 return true;
02668 break;
02669 default:
02670
02671 return (r < l);
02672 break;
02673 }
02674 break;
02675 }
02676 }
02677
02678
02679
02680
02681
02682 Theorem ArithTheoremProducerOld::IsIntegerElim(const Theorem& isIntx)
02683 {
02684 Expr expr = isIntx.getExpr();
02685 if (CHECK_PROOFS) {
02686 CHECK_SOUND(expr.getKind() == IS_INTEGER,
02687 "Expected IS_INTEGER predicate");
02688 }
02689 expr = expr[0];
02690 DebugAssert(!d_theoryArith->isInteger(expr), "Expected non-integer");
02691
02692 Assumptions a(isIntx);
02693 Proof pf;
02694
02695 if (withProof())
02696 {
02697 pf = newPf("isIntElim", isIntx.getProof());
02698 }
02699
02700 Expr newVar = d_em->newBoundVarExpr(d_theoryArith->intType());
02701 Expr res = d_em->newClosureExpr(EXISTS, newVar, newVar.eqExpr(expr));
02702
02703 return newTheorem(res, a, pf);
02704 }
02705
02706
02707 Theorem
02708 ArithTheoremProducerOld::eqElimIntRule(const Theorem& eqn, const Theorem& isIntx,
02709 const vector<Theorem>& isIntVars) {
02710 TRACE("arith eq", "eqElimIntRule(", eqn.getExpr(), ") {");
02711 Proof pf;
02712
02713 if(CHECK_PROOFS)
02714 CHECK_SOUND(eqn.isRewrite(),
02715 "ArithTheoremProducerOld::eqElimInt: input must be an equation" +
02716 eqn.toString());
02717
02718 const Expr& lhs = eqn.getLHS();
02719 const Expr& rhs = eqn.getRHS();
02720 Expr a, x;
02721 d_theoryArith->separateMonomial(lhs, a, x);
02722
02723 if(CHECK_PROOFS) {
02724
02725 const Expr& isIntxe = isIntx.getExpr();
02726 CHECK_SOUND(isIntPred(isIntxe) && isIntxe[0] == x,
02727 "ArithTheoremProducerOld::eqElimInt\n eqn = "
02728 +eqn.getExpr().toString()
02729 +"\n isIntx = "+isIntxe.toString());
02730 CHECK_SOUND(isRational(a) && a.getRational().isInteger()
02731 && a.getRational() >= 2,
02732 "ArithTheoremProducerOld::eqElimInt:\n lhs = "+lhs.toString());
02733
02734
02735 CHECK_SOUND(!isDivide(rhs),
02736 "ArithTheoremProducerOld::eqElimInt:\n rhs = "+rhs.toString());
02737
02738 if(!isPlus(rhs)) {
02739 Expr c, v;
02740 d_theoryArith->separateMonomial(rhs, c, v);
02741 CHECK_SOUND(isIntVars.size() == 1
02742 && isIntPred(isIntVars[0].getExpr())
02743 && isIntVars[0].getExpr()[0] == v
02744 && isRational(c) && c.getRational().isInteger(),
02745 "ArithTheoremProducerOld::eqElimInt:\n rhs = "+rhs.toString()
02746 +"isIntVars.size = "+int2string(isIntVars.size()));
02747 } else {
02748 CHECK_SOUND(isIntVars.size() + 1 == (size_t)rhs.arity(),
02749 "ArithTheoremProducerOld::eqElimInt: rhs = "+rhs.toString());
02750
02751 CHECK_SOUND(isRational(rhs[0]) && rhs[0].getRational().isInteger(),
02752 "ArithTheoremProducerOld::eqElimInt: rhs = "+rhs.toString());
02753
02754 for(size_t i=0, iend=isIntVars.size(); i<iend; ++i) {
02755 Expr c, v;
02756 d_theoryArith->separateMonomial(rhs[i+1], c, v);
02757 const Expr& isInt(isIntVars[i].getExpr());
02758 CHECK_SOUND(isIntPred(isInt) && isInt[0] == v
02759 && isRational(c) && c.getRational().isInteger(),
02760 "ArithTheoremProducerOld::eqElimInt:\n rhs["+int2string(i+1)
02761 +"] = "+rhs[i+1].toString()
02762 +"\n isInt = "+isInt.toString());
02763 }
02764 }
02765 }
02766
02767
02768 static int varCount(0);
02769 Expr newVar = d_em->newBoundVarExpr("_int_var", int2string(varCount++));
02770 newVar.setType(intType());
02771 Expr t2 = create_t2(lhs, rhs, newVar);
02772 Expr t3 = create_t3(lhs, rhs, newVar);
02773 vector<Expr> vars;
02774 vars.push_back(newVar);
02775 Expr res = d_em->newClosureExpr(EXISTS, vars,
02776 x.eqExpr(t2) && rat(0).eqExpr(t3));
02777
02778 vector<Theorem> thms(isIntVars);
02779 thms.push_back(isIntx);
02780 thms.push_back(eqn);
02781 Assumptions assump(thms);
02782
02783 if(withProof()) {
02784 vector<Proof> pfs;
02785 pfs.push_back(eqn.getProof());
02786 pfs.push_back(isIntx.getProof());
02787 vector<Theorem>::const_iterator i=isIntVars.begin(), iend=isIntVars.end();
02788 for(; i!=iend; ++i)
02789 pfs.push_back(i->getProof());
02790 pf = newPf("eq_elim_int", eqn.getExpr(), res, pfs);
02791 }
02792
02793 Theorem thm(newTheorem(res, assump, pf));
02794 TRACE("arith eq", "eqElimIntRule => ", thm.getExpr(), " }");
02795 return thm;
02796 }
02797
02798
02799 Theorem
02800 ArithTheoremProducerOld::isIntConst(const Expr& e) {
02801 Proof pf;
02802
02803 if(CHECK_PROOFS) {
02804 CHECK_SOUND(isIntPred(e) && e[0].isRational(),
02805 "ArithTheoremProducerOld::isIntConst(e = "
02806 +e.toString()+")");
02807 }
02808 if(withProof())
02809 pf = newPf("is_int_const", e);
02810 bool isInt = e[0].getRational().isInteger();
02811 return newRWTheorem(e, isInt? d_em->trueExpr() : d_em->falseExpr(), Assumptions::emptyAssump(), pf);
02812 }
02813
02814
02815 Theorem
02816 ArithTheoremProducerOld::equalLeaves1(const Theorem& thm)
02817 {
02818 Proof pf;
02819 const Expr& e = thm.getRHS();
02820
02821 if (CHECK_PROOFS) {
02822 CHECK_SOUND(e[1].getKind() == RATIONAL_EXPR &&
02823 e[1].getRational() == Rational(0) &&
02824 e[0].getKind() == PLUS &&
02825 e[0].arity() == 3 &&
02826 e[0][0].getKind() == RATIONAL_EXPR &&
02827 e[0][0].getRational() == Rational(0) &&
02828 e[0][1].getKind() == MULT &&
02829 e[0][1].arity() == 2 &&
02830 e[0][1][0].getKind() == RATIONAL_EXPR &&
02831 e[0][1][0].getRational() == Rational(-1),
02832 "equalLeaves1");
02833 }
02834 if (withProof())
02835 {
02836 vector<Proof> pfs;
02837 pfs.push_back(thm.getProof());
02838 pf = newPf("equalLeaves1", e, pfs);
02839 }
02840 return newRWTheorem(e, e[0][1][1].eqExpr(e[0][2]), thm.getAssumptionsRef(), pf);
02841 }
02842
02843
02844 Theorem
02845 ArithTheoremProducerOld::equalLeaves2(const Theorem& thm)
02846 {
02847 Proof pf;
02848 const Expr& e = thm.getRHS();
02849
02850 if (CHECK_PROOFS) {
02851 CHECK_SOUND(e[0].getKind() == RATIONAL_EXPR &&
02852 e[0].getRational() == Rational(0) &&
02853 e[1].getKind() == PLUS &&
02854 e[1].arity() == 3 &&
02855 e[1][0].getKind() == RATIONAL_EXPR &&
02856 e[1][0].getRational() == Rational(0) &&
02857 e[1][1].getKind() == MULT &&
02858 e[1][1].arity() == 2 &&
02859 e[1][1][0].getKind() == RATIONAL_EXPR &&
02860 e[1][1][0].getRational() == Rational(-1),
02861 "equalLeaves2");
02862 }
02863 if (withProof())
02864 {
02865 vector<Proof> pfs;
02866 pfs.push_back(thm.getProof());
02867 pf = newPf("equalLeaves2", e, pfs);
02868 }
02869 return newRWTheorem(e, e[1][1][1].eqExpr(e[1][2]), thm.getAssumptionsRef(), pf);
02870 }
02871
02872
02873 Theorem
02874 ArithTheoremProducerOld::equalLeaves3(const Theorem& thm)
02875 {
02876 Proof pf;
02877 const Expr& e = thm.getRHS();
02878
02879 if (CHECK_PROOFS) {
02880 CHECK_SOUND(e[1].getKind() == RATIONAL_EXPR &&
02881 e[1].getRational() == Rational(0) &&
02882 e[0].getKind() == PLUS &&
02883 e[0].arity() == 3 &&
02884 e[0][0].getKind() == RATIONAL_EXPR &&
02885 e[0][0].getRational() == Rational(0) &&
02886 e[0][2].getKind() == MULT &&
02887 e[0][2].arity() == 2 &&
02888 e[0][2][0].getKind() == RATIONAL_EXPR &&
02889 e[0][2][0].getRational() == Rational(-1),
02890 "equalLeaves3");
02891 }
02892 if (withProof())
02893 {
02894 vector<Proof> pfs;
02895 pfs.push_back(thm.getProof());
02896 pf = newPf("equalLeaves3", e, pfs);
02897 }
02898 return newRWTheorem(e, e[0][2][1].eqExpr(e[0][1]), thm.getAssumptionsRef(), pf);
02899 }
02900
02901
02902 Theorem
02903 ArithTheoremProducerOld::equalLeaves4(const Theorem& thm)
02904 {
02905 Proof pf;
02906 const Expr& e = thm.getRHS();
02907
02908 if (CHECK_PROOFS) {
02909 CHECK_SOUND(e[0].getKind() == RATIONAL_EXPR &&
02910 e[0].getRational() == Rational(0) &&
02911 e[1].getKind() == PLUS &&
02912 e[1].arity() == 3 &&
02913 e[1][0].getKind() == RATIONAL_EXPR &&
02914 e[1][0].getRational() == Rational(0) &&
02915 e[1][2].getKind() == MULT &&
02916 e[1][2].arity() == 2 &&
02917 e[1][2][0].getKind() == RATIONAL_EXPR &&
02918 e[1][2][0].getRational() == Rational(-1),
02919 "equalLeaves4");
02920 }
02921 if (withProof())
02922 {
02923 vector<Proof> pfs;
02924 pfs.push_back(thm.getProof());
02925 pf = newPf("equalLeaves4", e, pfs);
02926 }
02927 return newRWTheorem(e, e[1][2][1].eqExpr(e[1][1]), thm.getAssumptionsRef(), pf);
02928 }
02929
02930 Theorem
02931 ArithTheoremProducerOld::diseqToIneq(const Theorem& diseq) {
02932 Proof pf;
02933
02934 const Expr& e = diseq.getExpr();
02935
02936 if(CHECK_PROOFS) {
02937 CHECK_SOUND(e.isNot() && e[0].isEq(),
02938 "ArithTheoremProducerOld::diseqToIneq: expected disequality:\n"
02939 " e = "+e.toString());
02940 }
02941
02942 const Expr& x = e[0][0];
02943 const Expr& y = e[0][1];
02944
02945 if(withProof())
02946 pf = newPf(e, diseq.getProof());
02947 return newTheorem(ltExpr(x,y).orExpr(gtExpr(x,y)), diseq.getAssumptionsRef(), pf);
02948 }
02949
02950 Theorem ArithTheoremProducerOld::dummyTheorem(const Expr& e) {
02951 Proof pf;
02952 return newRWTheorem(e, d_em->trueExpr(), Assumptions::emptyAssump(), pf);
02953 }
02954
02955 Theorem ArithTheoremProducerOld::oneElimination(const Expr& e) {
02956
02957
02958 if (CHECK_PROOFS)
02959 CHECK_SOUND(isMult(e) &&
02960 e.arity() == 2 &&
02961 e[0].isRational() &&
02962 e[0].getRational() == 1,
02963 "oneElimination: input must be a multiplication by one" + e.toString());
02964
02965
02966 Proof pf;
02967
02968
02969 if (withProof())
02970 pf = newPf("oneElimination", e);
02971
02972
02973 return newRWTheorem(e, e[1], Assumptions::emptyAssump(), pf);
02974 }
02975
02976 Theorem ArithTheoremProducerOld::clashingBounds(const Theorem& lowerBound, const Theorem& upperBound) {
02977
02978
02979 const Expr& lowerBoundExpr = lowerBound.getExpr();
02980 const Expr& upperBoundExpr = upperBound.getExpr();
02981
02982
02983 if (CHECK_PROOFS) {
02984 CHECK_SOUND(isLE(lowerBoundExpr) || isLT(lowerBoundExpr), "clashingBounds: lowerBound should be >= or > " + lowerBoundExpr.toString());
02985 CHECK_SOUND(isGE(upperBoundExpr) || isGT(upperBoundExpr), "clashingBounds: upperBound should be <= or < " + upperBoundExpr.toString());
02986 CHECK_SOUND(lowerBoundExpr[0].isRational(), "clashingBounds: lowerBound left side should be a rational " + lowerBoundExpr.toString());
02987 CHECK_SOUND(upperBoundExpr[0].isRational(), "clashingBounds: upperBound left side should be a rational " + upperBoundExpr.toString());
02988 CHECK_SOUND(lowerBoundExpr[1] == upperBoundExpr[1], "clashingBounds: bounds not on the same term " + lowerBoundExpr.toString() + ", " + upperBoundExpr.toString());
02989
02990
02991 Rational lowerBoundR = lowerBoundExpr[0].getRational();
02992 Rational upperBoundR = upperBoundExpr[0].getRational();
02993
02994 if (isLE(lowerBoundExpr) && isGE(upperBoundExpr)) {
02995 CHECK_SOUND(upperBoundR < lowerBoundR, "clashingBounds: bounds are satisfiable");
02996 } else {
02997 CHECK_SOUND(upperBoundR <= lowerBoundR, "clashingBounds: bounds are satisfiable");
02998 }
02999 }
03000
03001
03002 Proof pf;
03003
03004 if (withProof())
03005 pf = newPf("clashingBounds", lowerBoundExpr, upperBoundExpr);
03006
03007
03008 Assumptions assumptions;
03009 assumptions.add(lowerBound);
03010 assumptions.add(upperBound);
03011
03012
03013 return newTheorem(d_em->falseExpr(), assumptions, pf);
03014 }
03015
03016 Theorem ArithTheoremProducerOld::addInequalities(const Theorem& thm1, const Theorem& thm2) {
03017
03018
03019 const Expr& expr1 = thm1.getExpr();
03020 const Expr& expr2 = thm2.getExpr();
03021
03022
03023 if (CHECK_PROOFS) {
03024
03025 CHECK_SOUND(isIneq(expr1), "addInequalities: expecting an inequality for thm1, got " + expr1.toString());
03026 CHECK_SOUND(isIneq(expr2), "addInequalities: expecting an inequality for thm2, got " + expr2.toString());
03027
03028 if (isLE(expr1) || isLT(expr1))
03029 CHECK_SOUND(isLE(expr2) || isLT(expr2), "addInequalities: expr2 should be <(=) also " + expr2.toString());
03030 if (isGE(expr1) || isGT(expr1))
03031 CHECK_SOUND(isGE(expr2) || isGT(expr2), "addInequalities: expr2 should be >(=) also" + expr2.toString());
03032 }
03033
03034
03035 Assumptions a(thm1, thm2);
03036
03037
03038 int kind1 = expr1.getKind();
03039 int kind2 = expr2.getKind();
03040
03041
03042 int kind = (kind1 == kind2) ? kind1 : ((kind1 == LT) || (kind2 == LT))? LT : GT;
03043
03044
03045 Proof pf;
03046 if(withProof()) {
03047 vector<Proof> pfs;
03048 pfs.push_back(thm1.getProof());
03049 pfs.push_back(thm2.getProof());
03050 pf = newPf("addInequalities", expr1, expr2, pfs);
03051 }
03052
03053
03054 Expr leftSide = plusExpr(expr1[0], expr2[0]);
03055 Expr rightSide = plusExpr(expr1[1], expr2[1]);
03056
03057
03058 return newTheorem(Expr(kind, leftSide, rightSide), a, pf);
03059 }
03060
03061
03062
03063
03064
03065 Theorem ArithTheoremProducerOld::implyWeakerInequality(const Expr& expr1, const Expr& expr2) {
03066
03067
03068 if (CHECK_PROOFS) {
03069
03070
03071 CHECK_SOUND(isIneq(expr1), "implyWeakerInequality: expr1 should be an inequality" + expr1.toString());
03072 CHECK_SOUND(isIneq(expr2), "implyWeakerInequality: expr1 should be an inequality" + expr2.toString());
03073
03074
03075 CHECK_SOUND(expr1[0].isRational() && expr1[0].getRational() == 0, "implyWeakerInequality: expr1 should have a rational on the left side" + expr1.toString());
03076 CHECK_SOUND(expr2[0].isRational() && expr2[0].getRational() == 0, "implyWeakerInequality: expr2 should have a rational on the left side" + expr2.toString());
03077
03078
03079 Rational c1 = 0;
03080 vector<Expr> t1_children;
03081 if (isPlus(expr1[1])) {
03082 int start_i = 0;
03083 if (expr1[1][0].isRational()) {
03084 start_i = 1;
03085 c1 = expr1[1][0].getRational();
03086 }
03087 int end_i = expr1[1].arity();
03088 for(int i = start_i; i < end_i; i ++) {
03089 const Expr& term = expr1[1][i];
03090 t1_children.push_back(term);
03091 }
03092 } else
03093 t1_children.push_back(expr1[1]);
03094 Expr t1 = (t1_children.size() > 1 ? plusExpr(t1_children) : t1_children[0]);
03095
03096
03097 Rational c2 = 0;
03098 vector<Expr> t2_children;
03099 if (isPlus(expr2[1])) {
03100 int start_i = 0;
03101 if (expr2[1][0].isRational()) {
03102 start_i = 1;
03103 c2 = expr2[1][0].getRational();
03104 }
03105 int end_i = expr2[1].arity();
03106 for(int i = start_i; i < end_i; i ++) {
03107 const Expr& term = expr2[1][i];
03108 t2_children.push_back(term);
03109 }
03110 } else
03111 t2_children.push_back(expr2[1]);
03112 Expr t2 = (t2_children.size() > 1 ? plusExpr(t2_children) : t2_children[0]);
03113
03114 CHECK_SOUND(t2 == t1, "implyWeakerInequality: terms different " + t1.toString() + " vs " + t2.toString());
03115 CHECK_SOUND(c2 > c1 || (c2 == c1 && !(expr1.getKind() == LE && expr2.getKind() == LT)), "implyWeakerInequality: c2 is not bigger than c1" + expr1.toString() + " --> " + expr2.toString());
03116 }
03117
03118 Proof pf;
03119 if(withProof()) pf = newPf("implyWeakerInequality", expr1, expr2);
03120
03121
03122 return newTheorem(expr1.impExpr(expr2), Assumptions::emptyAssump(), pf);
03123 }
03124
03125
03126
03127
03128
03129
03130
03131 Theorem ArithTheoremProducerOld::implyNegatedInequality(const Expr& expr1, const Expr& expr2) {
03132
03133
03134
03135 if (CHECK_PROOFS) {
03136
03137
03138 CHECK_SOUND(isIneq(expr1), "implyNegatedInequality: expr1 should be an inequality" + expr1.toString());
03139 CHECK_SOUND(isIneq(expr2), "implyNegatedInequality: expr1 should be an inequality" + expr2.toString());
03140
03141
03142 CHECK_SOUND(expr1[0].isRational() && expr1[0].getRational() == 0, "implyNegatedInequality: expr1 should have a rational on the left side" + expr1.toString());
03143 CHECK_SOUND(expr2[0].isRational() && expr2[0].getRational() == 0, "implyNegatedInequality: expr2 should have a rational on the left side" + expr2.toString());
03144
03145
03146 Rational c1 = 0;
03147 vector<Expr> t1_children;
03148 if (isPlus(expr1[1])) {
03149 int start_i = 0;
03150 if (expr1[1][0].isRational()) {
03151 start_i = 1;
03152 c1 = expr1[1][0].getRational();
03153 }
03154 int end_i = expr1[1].arity();
03155 for(int i = start_i; i < end_i; i ++) {
03156 const Expr& term = expr1[1][i];
03157 t1_children.push_back(term);
03158 }
03159 } else
03160 t1_children.push_back(expr1[1]);
03161 Expr t1 = (t1_children.size() > 1 ? plusExpr(t1_children) : t1_children[0]);
03162
03163
03164 Rational c2 = 0;
03165 vector<Expr> t2_children;
03166 if (isPlus(expr2[1])) {
03167 int start_i = 0;
03168 if (expr2[1][0].isRational()) {
03169 start_i = 1;
03170 c2 = expr2[1][0].getRational();
03171 }
03172 int end_i = expr2[1].arity();
03173 for(int i = start_i; i < end_i; i ++) {
03174 const Expr& term = expr2[1][i];
03175 t2_children.push_back(term);
03176 }
03177 } else
03178 t2_children.push_back(expr2[1]);
03179 Expr t2 = (t2_children.size() > 1 ? plusExpr(t2_children) : t2_children[0]);
03180
03181
03182 if (isPlus(t1) && isPlus(t2)) {
03183 CHECK_SOUND(t1.arity() == t2.arity(), "implyNegatedInequality: t1 should be -t2 : " + t1.toString() + " vs " + t2.toString());
03184 for (int i = 0; i < t1.arity(); i++) {
03185 Expr term_t1 = t1[i];
03186 Expr term_t2 = t2[i];
03187 Rational t1_c = (isMult(term_t1) ? term_t1[0].getRational() : 1);
03188 term_t1 = (isMult(term_t1) ? term_t1[1] : term_t1);
03189 Rational t2_c = (isMult(term_t2) ? term_t2[0].getRational() : 1);
03190 term_t2 = (isMult(term_t2) ? term_t2[1] : term_t2);
03191 CHECK_SOUND(t1_c == - t2_c, "implyNegatedInequality: t1 should be -t2 : " + t1.toString() + " vs " + t2.toString());
03192 CHECK_SOUND(term_t1 == term_t2, "implyNegatedInequality: t1 should be -t2 : " + t1.toString() + " vs " + t2.toString());
03193 }
03194 } else {
03195 Rational t1_c = (isMult(t1) ? t1[0].getRational() : 1);
03196 Expr term_t1 = (isMult(t1) ? t1[1] : t1);
03197 Rational t2_c = (isMult(t2) ? t2[0].getRational() : 1);
03198 Expr term_t2 = (isMult(t2) ? t2[1] : t2);
03199 CHECK_SOUND(t1_c == - t2_c, "implyNegatedInequality: t1 should be -t2 : " + t1.toString() + " vs " + t2.toString());
03200 CHECK_SOUND(term_t1 == term_t2, "implyNegatedInequality: t1 should be -t2 : " + t1.toString() + " vs " + t2.toString());
03201 }
03202
03203 int kind1 = expr1.getKind();
03204 int kind2 = expr2.getKind();
03205 bool bothStrict = kind1 == LT && kind2 == LT;
03206 CHECK_SOUND(c1 + c2 < 0 || (c1 + c2 == 0 && bothStrict), "implyNegatedInequality: sum of constants not negative!");
03207 }
03208
03209
03210 Proof pf;
03211 if (withProof()) pf = newPf("implyNegatedInequality", expr1, expr2, expr2.negate());
03212
03213
03214 return newTheorem(expr1.impExpr(expr2.negate()), Assumptions::emptyAssump(), pf);
03215 }
03216
03217 Theorem ArithTheoremProducerOld::trustedRewrite(const Expr& expr1, const Expr& expr2) {
03218
03219
03220 Proof pf;
03221
03222
03223 if (withProof()) pf = newPf("trustedRewrite", expr1, expr2);
03224
03225
03226 return newRWTheorem(expr1, expr2, Assumptions::emptyAssump(), pf);
03227
03228 }
03229
03230 Theorem ArithTheoremProducerOld::integerSplit(const Expr& intVar, const Rational& intPoint) {
03231
03232
03233 if (CHECK_PROOFS) {
03234 CHECK_SOUND(intPoint.isInteger(), "integerSplit: we can only split on integer points, given" + intPoint.toString());
03235 }
03236
03237
03238 const Expr& split = Expr(IS_INTEGER, intVar).impExpr(leExpr(intVar, rat(intPoint)).orExpr(geExpr(intVar, rat(intPoint + 1))));
03239
03240
03241 Proof pf;
03242 if (withProof()) pf = newPf("integerSplit", intVar, rat(intPoint));
03243
03244
03245 return newTheorem(split, Assumptions::emptyAssump(), pf);
03246 }
03247
03248
03249
03250
03251
03252
03253 Theorem ArithTheoremProducerOld::rafineStrictInteger(const Theorem& isIntConstrThm, const Expr& constr) {
03254
03255
03256 if (CHECK_PROOFS) {
03257
03258 CHECK_SOUND(isIneq(constr), "rafineStrictInteger: expected a constraint got : " + constr.toString());
03259 CHECK_SOUND(constr[0].isRational() && constr[0].getRational() == 0, "rafineStrictInteger: left hand side must be 0");
03260 CHECK_SOUND(d_theoryArith->isLeaf(constr[1]) || constr[1][0].isRational(), "rafineStrictInteger: right side of the constraint must be a leaf or a sum, with the first one a rational");
03261
03262
03263 Expr intSum = isIntConstrThm.getExpr()[0];
03264 Expr ineqSum = constr[1];
03265 if (isPlus(intSum)) {
03266 int i, j;
03267 for (i = 0, j = 1; i < intSum.arity() && j < ineqSum.arity(); i ++, j ++)
03268 if (!(intSum[i] == ineqSum[j])) break;
03269 CHECK_SOUND(i == intSum.arity() && j == ineqSum.arity(), "rafineStrictInteger: proof of intger doesn't correspond to the constarint right side");
03270 } else
03271 CHECK_SOUND(intSum == ineqSum || intSum == ineqSum[1], "rafineStrictInteger: proof of intger doesn't correspond to the constarint right side:" + intSum.getString() + " vs " + ineqSum[1].getString());
03272 }
03273
03274
03275 Rational c = (isPlus(constr[1]) ? constr[1][0].getRational() : 0);
03276
03277
03278 int kind = constr.getKind();
03279
03280
03281 switch (kind) {
03282 case LT:
03283 kind = LE;
03284 if (c.isInteger()) c --;
03285 else c = floor(c);
03286 break;
03287 case LE:
03288 kind = LE;
03289 if (!c.isInteger()) c = floor(c);
03290 break;
03291 case GT:
03292 kind = GE;
03293 if (c.isInteger()) c ++;
03294 else c = ceil(c);
03295 break;
03296 case GE:
03297 kind = GE;
03298 if (!c.isInteger()) c = ceil(c);
03299 break;
03300 }
03301
03302
03303 vector<Expr> newChildren;
03304 if (isPlus(constr[1])) {
03305 for (int i = 0; i < constr[1].arity(); i ++)
03306 if (constr[1][i].isRational()) newChildren.push_back(rat(c));
03307 else newChildren.push_back(constr[1][i]);
03308 } else {
03309 if (c != 0) newChildren.push_back(rat(c));
03310 newChildren.push_back(constr[1]);
03311 }
03312 Expr newSum = newChildren.size() > 1 ? plusExpr(newChildren) : newChildren[0];
03313 Expr newConstr(kind, rat(0), newSum);
03314
03315
03316 const Assumptions& assump(isIntConstrThm.getAssumptionsRef());
03317
03318
03319 Proof pf;
03320 if (withProof())
03321 pf = newPf("rafineStrictInteger", constr, isIntConstrThm.getProof());
03322
03323
03324 return newRWTheorem(constr, newConstr, assump, pf);
03325 }
03326
03327
03328
03329
03330
03331
03332 Theorem ArithTheoremProducerOld::intEqualityRationalConstant(const Theorem& isIntConstrThm, const Expr& constr) {
03333
03334
03335 if (CHECK_PROOFS) {
03336
03337 CHECK_SOUND(constr.getKind() == EQ, "intEqualityRationalConstant: expected a constraint got : " + constr.toString());
03338 bool sum_on_rhs = (constr[0].isRational() && constr[0].getRational() == 0);
03339 bool sum_on_lhs = (constr[1].isRational() && constr[1].getRational() == 0);
03340 CHECK_SOUND((sum_on_rhs && !sum_on_lhs) ||(!sum_on_rhs && sum_on_lhs),
03341 "intEqualityRationalConstant: left or right hand side must be 0");
03342 CHECK_SOUND((sum_on_rhs && constr[1][0].isRational() && !constr[1][0].getRational().isInteger()) ||
03343 (sum_on_lhs && constr[0][0].isRational() && !constr[0][0].getRational().isInteger()),
03344 "intEqualityRationalConstant: left or right side of the constraint must be a sum, with the first one a rational (non integer)");
03345
03346
03347 Expr intSum = isIntConstrThm.getExpr()[0];
03348 Expr eqSum = (sum_on_lhs ? constr[0] : constr[1]);
03349 if (isPlus(intSum)) {
03350 int i, j;
03351 for (i = 0, j = 1; i < intSum.arity() && j < eqSum.arity(); i ++, j ++)
03352 if (!(intSum[i] == eqSum[j])) break;
03353 CHECK_SOUND(i == intSum.arity() && j == eqSum.arity(), "intEqualityRationalConstant: proof of intger doesn't correspond to the constarint right side");
03354 } else
03355 CHECK_SOUND(intSum == eqSum[1], "intEqualityRationalConstant: proof of intger doesn't correspond to the constarint right side:" + intSum.getString() + " vs " + eqSum[1].getString());
03356 }
03357
03358 const Assumptions& assump(isIntConstrThm.getAssumptionsRef());
03359
03360
03361 Proof pf;
03362 if (withProof())
03363 pf = newPf("intEqualityRationalConstant", constr, isIntConstrThm.getProof());
03364
03365
03366 return newRWTheorem(constr, d_em->falseExpr(), assump, pf);
03367 }
03368
03369 Theorem ArithTheoremProducerOld::cycleConflict(const vector<Theorem>& inequalitites) {
03370 Proof pf;
03371 if(withProof()) {
03372 vector<Expr> es;
03373 vector<Proof> pfs;
03374 for(unsigned i = 0; i < inequalitites.size(); i++) {
03375 es.push_back(inequalitites[i].getExpr());
03376 pfs.push_back(inequalitites[i].getProof());
03377 }
03378 pf = newPf("cycleConflict", es, pfs);
03379 }
03380
03381 Assumptions a;
03382 for(unsigned i = 0; i < inequalitites.size(); i ++)
03383 a.add(inequalitites[i]);
03384
03385 return newTheorem(d_em->falseExpr(), a, pf);
03386 }
03387
03388 Theorem ArithTheoremProducerOld::implyEqualities(const std::vector<Theorem>& inequalities) {
03389 Assumptions a;
03390 vector<Expr> conjuncts;
03391 for(unsigned i = 0; i < inequalities.size(); i ++) {
03392 a.add(inequalities[i]);
03393 Expr inequality = inequalities[i].getExpr();
03394 Expr equality = inequality[0].eqExpr(inequality[1]);
03395 conjuncts.push_back(equality);
03396 }
03397
03398 Proof pf;
03399 if(withProof()) {
03400 vector<Expr> es;
03401 vector<Proof> pfs;
03402 for(unsigned i = 0; i < inequalities.size(); i++) {
03403 es.push_back(inequalities[i].getExpr());
03404 pfs.push_back(inequalities[i].getProof());
03405 }
03406 pf = newPf("implyEqualities", Expr(RAW_LIST,conjuncts),Expr(RAW_LIST,es), pfs);
03407 }
03408
03409 return newTheorem(andExpr(conjuncts), a, pf);
03410 }
03411
03412
03413
03414
03415
03416 Theorem ArithTheoremProducerOld::lessThanToLERewrite(const Expr& ineq,
03417 const Theorem& isIntLHS,
03418 const Theorem& isIntRHS,
03419 bool changeRight) {
03420
03421 const Expr& isIntLHSexpr = isIntLHS.getExpr();
03422 const Expr& isIntRHSexpr = isIntRHS.getExpr();
03423
03424 if(CHECK_PROOFS) {
03425 CHECK_SOUND(isLT(ineq), "ArithTheoremProducerOld::LTtoLE: ineq must be <");
03426
03427 CHECK_SOUND(isIntPred(isIntLHSexpr) && isIntLHSexpr[0] == ineq[0],
03428 "ArithTheoremProducerOld::lessThanToLE: bad integrality check:\n"
03429 " ineq = "+ineq.toString()+"\n isIntLHS = "
03430 +isIntLHSexpr.toString());
03431 CHECK_SOUND(isIntPred(isIntRHSexpr) && isIntRHSexpr[0] == ineq[1],
03432 "ArithTheoremProducerOld::lessThanToLE: bad integrality check:\n"
03433 " ineq = "+ineq.toString()+"\n isIntRHS = "
03434 +isIntRHSexpr.toString());
03435 }
03436
03437 vector<Theorem> thms;
03438 thms.push_back(isIntLHS);
03439 thms.push_back(isIntRHS);
03440 Assumptions a(thms);
03441 Proof pf;
03442 Expr le = changeRight? leExpr(ineq[0], ineq[1] + rat(-1)) : leExpr(ineq[0] + rat(1), ineq[1]);
03443 if(withProof()) {
03444 vector<Proof> pfs;
03445 pfs.push_back(isIntLHS.getProof());
03446 pfs.push_back(isIntRHS.getProof());
03447 pf = newPf(changeRight? "lessThan_To_LE_rhs_rwr" : "lessThan_To_LE_lhs_rwr", ineq, le, pfs);
03448 }
03449
03450 return newRWTheorem(ineq, le, a, pf);
03451 }
03452
03453
03454
03455
03456 Theorem ArithTheoremProducerOld::splitGrayShadowSmall(const Theorem& gThm) {
03457 const Expr& theShadow = gThm.getExpr();
03458 if(CHECK_PROOFS) {
03459 CHECK_SOUND(isGrayShadow(theShadow),
03460 "ArithTheoremProducerOld::expandGrayShadowConst: not a shadow" +
03461 theShadow.toString());
03462 }
03463
03464 const Rational& c1 = theShadow[2].getRational();
03465 const Rational& c2 = theShadow[3].getRational();
03466
03467 if(CHECK_PROOFS) {
03468 CHECK_SOUND(c1.isInteger() && c2.isInteger() && c1 < c2,
03469 "ArithTheoremProducerOld::expandGrayShadow: " +
03470 theShadow.toString());
03471 }
03472
03473 const Expr& v = theShadow[0];
03474 const Expr& e = theShadow[1];
03475
03476 vector<Expr> disjuncts;
03477 for (int i = c1.getInt(); i <= c2.getInt(); i ++) {
03478 Expr disjunct = v.eqExpr(e + rat(i));
03479 disjuncts.push_back(disjunct);
03480 }
03481 Expr bigOr = orExpr(disjuncts);
03482
03483 Proof pf;
03484 if(withProof()){
03485 vector<Expr> exprs;
03486 exprs.push_back(theShadow);
03487 exprs.push_back(bigOr);
03488 pf = newPf("split_gray_shadow", exprs, gThm.getProof());
03489 }
03490
03491 return newTheorem(bigOr, gThm.getAssumptionsRef(), pf);
03492 }
03493
03494 Theorem ArithTheoremProducerOld::implyWeakerInequalityDiffLogic(const std::vector<Theorem>& antecedentThms, const Expr& implied) {
03495 Proof pf;
03496
03497 if(withProof()) {
03498 vector<Expr> es;
03499 vector<Proof> pfs;
03500 for(unsigned i = 0; i < antecedentThms.size(); i++) {
03501 es.push_back(antecedentThms[i].getExpr());
03502 pfs.push_back(antecedentThms[i].getProof());
03503 }
03504 pf = newPf("implyWeakerInequalityDiffLogic", implied, Expr(RAW_LIST,es), pfs);
03505 }
03506
03507 Assumptions a;
03508 for(unsigned i = 0; i < antecedentThms.size(); i ++) {
03509 a.add(antecedentThms[i]);
03510 }
03511
03512 return newTheorem(implied, a, pf);
03513
03514 }
03515
03516 Theorem ArithTheoremProducerOld::implyNegatedInequalityDiffLogic(const std::vector<Theorem>& antecedentThms, const Expr& implied) {
03517 Proof pf;
03518
03519 if(withProof()) {
03520 vector<Expr> es;
03521 vector<Proof> pfs;
03522 for(unsigned i = 0; i < antecedentThms.size(); i++) {
03523 es.push_back(antecedentThms[i].getExpr());
03524 pfs.push_back(antecedentThms[i].getProof());
03525 }
03526 pf = newPf("implyNegatedInequalityDiffLogic",implied.notExpr(), Expr(RAW_LIST, es), pfs);
03527 }
03528
03529 Assumptions a;
03530 for(unsigned i = 0; i < antecedentThms.size(); i ++) {
03531 a.add(antecedentThms[i]);
03532 }
03533
03534 return newTheorem(implied.notExpr(), a, pf);
03535
03536 }
03537
03538
03539 Theorem ArithTheoremProducerOld::expandGrayShadowRewrite(const Expr& theShadow) {
03540
03541 if(CHECK_PROOFS) {
03542 CHECK_SOUND(isGrayShadow(theShadow),
03543 "ArithTheoremProducerOld::expandGrayShadowConst: not a shadow" +
03544 theShadow.toString());
03545 }
03546
03547 const Rational& c1 = theShadow[2].getRational();
03548 const Rational& c2 = theShadow[3].getRational();
03549
03550 if(CHECK_PROOFS) {
03551 CHECK_SOUND(c1.isInteger() && c2.isInteger() && c1 < c2,
03552 "ArithTheoremProducerOld::expandGrayShadow: " +
03553 theShadow.toString());
03554 }
03555
03556 const Expr& v = theShadow[0];
03557 const Expr& e = theShadow[1];
03558
03559 Proof pf;
03560 if(withProof())
03561 pf = newPf("expand_gray_shadow", theShadow);
03562 Expr ineq1(leExpr(e+rat(c1), v));
03563 Expr ineq2(leExpr(v, e+rat(c2)));
03564 return newRWTheorem(theShadow, ineq1 && ineq2, Assumptions::emptyAssump(), pf);
03565 }
03566
03567 Theorem ArithTheoremProducerOld::compactNonLinearTerm(const Expr& nonLinear) {
03568
03569
03570 multiset<Expr> commonLeaves;
03571 bool first = true;
03572
03573
03574 for (int i = 0; i < nonLinear.arity(); i ++) {
03575 if (!nonLinear[i].isRational()) {
03576
03577 Expr monomial = nonLinear[i];
03578
03579
03580 multiset<Expr> currentLeaves;
03581
03582
03583 if (isMult(monomial)) {
03584 for (int j = 0; j < monomial.arity(); j ++)
03585 if (!monomial[j].isRational()) {
03586 if (isPow(monomial[j])) {
03587 for (int p = 0; p < monomial[j][0].getRational().getInt(); p ++)
03588 currentLeaves.insert(monomial[j][1]);
03589 } else
03590 currentLeaves.insert(monomial[j]);
03591 }
03592 } else if (isPow(monomial)) {
03593 for (int p = 0; p < monomial[0].getRational().getInt(); p ++)
03594 currentLeaves.insert(monomial[1]);
03595 } else
03596 currentLeaves.insert(monomial);
03597
03598
03599 if (first) {
03600 commonLeaves.swap(currentLeaves);
03601 first = false;
03602 } else {
03603 multiset<Expr> intersectLeaves;
03604 set_intersection(currentLeaves.begin(), currentLeaves.end(),
03605 commonLeaves.begin(), commonLeaves.end(),
03606 insert_iterator< multiset<Expr> >
03607 (intersectLeaves, intersectLeaves.begin()));
03608 intersectLeaves.swap(commonLeaves);
03609 }
03610 }
03611 }
03612
03613 Expr result;
03614 if (commonLeaves.size() > 0) {
03615
03616
03617 Expr constant = rat(0);
03618
03619
03620 vector<Expr> sumChildren;
03621
03622
03623 for (int i = 0; i < nonLinear.arity(); i ++) {
03624 if (!nonLinear[i].isRational()) {
03625
03626 Expr monomial = nonLinear[i];
03627
03628
03629 multiset<Expr> currentChildren;
03630
03631
03632 if (isMult(monomial)) {
03633 for (int j = 0; j < monomial.arity(); j ++)
03634 if (isPow(monomial[j])) {
03635 for (int p = 0; p < monomial[j][0].getRational().getInt(); p ++)
03636 currentChildren.insert(monomial[j][1]);
03637 } else
03638 currentChildren.insert(monomial[j]);
03639 } else if (isPow(monomial)) {
03640 for (int p = 0; p < monomial[0].getRational().getInt(); p ++)
03641 currentChildren.insert(monomial[1]);
03642 } else
03643 currentChildren.insert(monomial);
03644
03645
03646 multiset<Expr> diffChildren;
03647 set_difference(currentChildren.begin(), currentChildren.end(),
03648 commonLeaves.begin(), commonLeaves.end(),
03649 insert_iterator< multiset<Expr> >
03650 (diffChildren, diffChildren.begin()));
03651
03652
03653 if (diffChildren.size() == 1) {
03654 sumChildren.push_back(*diffChildren.begin());
03655 } else if (diffChildren.size() == 0) {
03656 sumChildren.push_back(rat(1));
03657 } else {
03658 multiset<Expr>::iterator it = diffChildren.begin();
03659 multiset<Expr>::iterator it_end = diffChildren.end();
03660 vector<Expr> multChildren;
03661 while (it != it_end) {
03662 multChildren.push_back(*it);
03663 it ++;
03664 }
03665 sumChildren.push_back(multExpr(multChildren));
03666 }
03667 } else
03668 constant = nonLinear[i];
03669 }
03670
03671
03672 vector<Expr> multChildren;
03673 multChildren.push_back(plusExpr(sumChildren));
03674 multiset<Expr>::iterator it = commonLeaves.begin();
03675 multiset<Expr>::iterator it_end = commonLeaves.end();
03676 for (; it != it_end; it ++)
03677 multChildren.push_back(*it);
03678 result = plusExpr(constant, multExpr(multChildren));
03679 } else {
03680
03681 result = nonLinear;
03682 }
03683
03684 Proof pf;
03685 if(withProof())
03686 pf = newPf("compactNonlinear", nonLinear);
03687
03688 return newRWTheorem(nonLinear, result, Assumptions::emptyAssump(), pf);
03689 }
03690
03691
03692
03693
03694
03695
03696
03697 Theorem ArithTheoremProducerOld::nonLinearIneqSignSplit(const Theorem& ineqThm) {
03698
03699
03700 Expr ineq = ineqThm.getExpr();
03701 Expr rhs = ineq[1];
03702
03703
03704 Rational c = (isMult(rhs) ? 0 : rhs[0].getRational());
03705 if(CHECK_PROOFS) {
03706 CHECK_SOUND(c <= 0, "ArithTheoremProducerOld::nonLinearIneqSignSplit: " + ineq.toString());
03707 CHECK_SOUND(isMult(rhs) || (isPlus(rhs) && rhs.arity() == 2), "ArithTheoremProducerOld::nonLinearIneqSignSplit: " + ineq.toString());
03708 }
03709
03710 Expr signXor = d_em->trueExpr();
03711 Expr mult = (isMult(rhs) ? rhs : rhs[1]);
03712 for (int i = 0; i < mult.arity(); i ++) {
03713 Expr term = mult[i];
03714 if (isPow(term) && term[0].getRational() < 0)
03715 term = Expr(POW, -term[0], term[1]);
03716 signXor = Expr(XOR, signXor, ltExpr(term, rat(0)));
03717 }
03718
03719 if (c == 0 && ineq.getKind() == LE) {
03720 Expr zeroOr = d_em->falseExpr();
03721 for (int i = 0; i < mult.arity(); i ++) {
03722 Expr term = mult[i];
03723 zeroOr = zeroOr.orExpr(term.eqExpr(rat(0)));
03724 }
03725 signXor = zeroOr.orExpr(signXor);
03726 }
03727
03728 Proof pf;
03729 if(withProof()) {
03730 vector<Expr> exprs;
03731 exprs.push_back(ineq);
03732 exprs.push_back(signXor);
03733 pf = newPf("nonLinearIneqSignSplit", exprs, ineqThm.getProof());
03734 }
03735
03736 Assumptions assumptions;
03737 assumptions.add(ineqThm);
03738
03739 return newTheorem(signXor, assumptions, pf);
03740 }
03741
03742 Theorem ArithTheoremProducerOld::implyDiffLogicBothBounds(const Expr& x,
03743 std::vector<Theorem>& c1_le_x, Rational c1,
03744 std::vector<Theorem>& x_le_c2, Rational c2)
03745 {
03746 Proof pf;
03747
03748 if(withProof()) {
03749 vector<Expr> es;
03750 vector<Proof> pfs;
03751 for(unsigned i = 0; i < c1_le_x.size(); i++) {
03752 es.push_back(c1_le_x[i].getExpr());
03753 pfs.push_back(c1_le_x[i].getProof());
03754 }
03755 for(unsigned i = 0; i < x_le_c2.size(); i++) {
03756 es.push_back(x_le_c2[i].getExpr());
03757 pfs.push_back(x_le_c2[i].getProof());
03758 }
03759 pf = newPf("implyDiffLogicBothBounds", es, pfs);
03760 }
03761
03762 Assumptions a;
03763 for(unsigned i = 0; i < x_le_c2.size(); i ++) {
03764 a.add(c1_le_x[i]);
03765 }
03766 for(unsigned i = 0; i < x_le_c2.size(); i ++) {
03767 a.add(c1_le_x[i]);
03768 }
03769
03770 Expr implied = grayShadow(x, rat(0), c1, c2);
03771
03772 return newTheorem(implied, a, pf);
03773 }
03774
03775 Theorem ArithTheoremProducerOld::addInequalities(const vector<Theorem>& thms) {
03776
03777
03778 if (CHECK_PROOFS) {
03779 for (unsigned i = 0; i < thms.size(); i ++) {
03780 Expr expr = thms[i].getExpr();
03781 CHECK_SOUND(isIneq(expr), "addInequalities: expecting an inequality for, got " + expr.toString());
03782 CHECK_SOUND(isLE(expr) || isLT(expr), "addInequalities: expr should be <(=) " + expr.toString());
03783 }
03784 }
03785
03786
03787 Assumptions a;
03788 for (unsigned i = 0; i < thms.size(); i ++)
03789 a.add(thms[i]);
03790
03791
03792 int kind = LE;
03793 for (unsigned i = 0; i < thms.size(); i ++)
03794 if (thms[i].getExpr().getKind() == LT) kind = LT;
03795
03796
03797 Proof pf;
03798 if(withProof()) {
03799 vector<Proof> pfs;
03800 vector<Expr> exps;
03801 for (unsigned i = 0; i < thms.size(); i ++) {
03802 pfs.push_back(thms[i].getProof());
03803 exps.push_back(thms[i].getExpr());
03804 }
03805 pf = newPf("addInequalities", exps, pfs);
03806 }
03807
03808
03809 vector<Expr> summandsLeft;
03810 vector<Expr> summandsRight;
03811 for (unsigned i = 0; i < thms.size(); i ++) {
03812 summandsLeft.push_back(thms[i].getExpr()[0]);
03813 summandsRight.push_back(thms[i].getExpr()[1]);
03814 }
03815 Expr leftSide = plusExpr(summandsLeft);
03816 Expr rightSide = plusExpr(summandsRight);
03817
03818
03819 return newTheorem(Expr(kind, leftSide, rightSide), a, pf);
03820 }
03821
03822
03823 Theorem ArithTheoremProducerOld::powerOfOne(const Expr& e) {
03824
03825 if(CHECK_PROOFS) {
03826 CHECK_SOUND(isPow(e), "ArithTheoremProducerOld::powerOfOne: not a power expression" + e.toString());
03827 CHECK_SOUND(e[0].isRational() && e[0].getRational() == 1, "ArithTheoremProducerOld::powerOfOne: not a power of 1" + e.toString());
03828 }
03829
03830 Proof pf;
03831 if(withProof())
03832 pf = newPf("power_of_one", e);
03833
03834 return newRWTheorem(e, e[1], Assumptions::emptyAssump(), pf);
03835 }
03836
03837
03838 void ArithTheoremProducerOld::getLeaves(const Expr& e, set<Rational>& s, ExprHashMap<bool>& cache)
03839 {
03840 if (e.isRational()) {
03841 s.insert(e.getRational());
03842 return;
03843 }
03844
03845 if (e.isAtomic() && d_theoryArith->isLeaf(e)) {
03846 return;
03847 }
03848
03849 ExprHashMap<bool>::iterator it = cache.find(e);
03850 if (it != cache.end()) return;
03851
03852 cache[e] = true;
03853
03854 DebugAssert(e.arity() > 0, "Expected non-zero arity");
03855 int k = 0;
03856
03857 if (e.isITE()) {
03858 k = 1;
03859 }
03860
03861 for (; k < e.arity(); ++k) {
03862 getLeaves(e[k], s, cache);
03863 }
03864 }
03865
03866
03867 Theorem ArithTheoremProducerOld::rewriteLeavesConst(const Expr& e)
03868 {
03869 DebugAssert(e.isPropAtom() && d_theoryArith->leavesAreNumConst(e),
03870 "invariant violated");
03871 DebugAssert(e.getKind() == EQ || e.getKind() == LT || e.getKind() == LE || e.getKind() == GT || e.getKind() == GE,
03872 "Unexpected kind");
03873 set<Rational> lhs, rhs;
03874 ExprHashMap<bool> cache;
03875 getLeaves(e[0], lhs, cache);
03876
03877 cache.clear();
03878 getLeaves(e[1], rhs, cache);
03879
03880 Expr res;
03881 switch (e.getKind()) {
03882 case EQ: {
03883 set<Rational> common;
03884 set_intersection(lhs.begin(), lhs.end(), rhs.begin(), rhs.end(),
03885 inserter(common, common.begin()));
03886 if (common.empty()) {
03887 res = d_em->falseExpr();
03888 }
03889 break;
03890 }
03891 case LT: {
03892 set<Rational>::iterator it;
03893 it = lhs.end();
03894 --it;
03895 if ((*it) < (*(rhs.begin()))) {
03896 res = d_em->trueExpr();
03897 } else {
03898 it = rhs.end();
03899 --it;
03900 if ((*it) <= (*(lhs.begin()))) {
03901 res = d_em->falseExpr();
03902 }
03903 }
03904 break;
03905 }
03906 case LE: {
03907 set<Rational>::iterator it;
03908 it = lhs.end();
03909 --it;
03910 if ((*it) <= (*(rhs.begin()))) {
03911 res = d_em->trueExpr();
03912 }
03913 else {
03914 it = rhs.end();
03915 --it;
03916 if ((*it) < (*(lhs.begin()))) {
03917 res = d_em->falseExpr();
03918 break;
03919 }
03920 }
03921 break;
03922 }
03923 case GT: {
03924 set<Rational>::iterator it;
03925 it = lhs.end();
03926 --it;
03927 if ((*it) > (*(rhs.begin()))) {
03928 res = d_em->trueExpr();
03929 } else {
03930 it = rhs.end();
03931 --it;
03932 if ((*it) >= (*(lhs.begin()))) {
03933 res = d_em->falseExpr();
03934 }
03935 }
03936 break;
03937 }
03938 case GE: {
03939 set<Rational>::iterator it;
03940 it = lhs.end();
03941 --it;
03942 if ((*it) >= (*(rhs.begin()))) {
03943 res = d_em->trueExpr();
03944 }
03945 else {
03946 it = rhs.end();
03947 --it;
03948 if ((*it) > (*(lhs.begin()))) {
03949 res = d_em->falseExpr();
03950 break;
03951 }
03952 }
03953 break;
03954 }
03955 default:
03956 break;
03957 }
03958 if (res.isNull()) return d_theoryArith->reflexivityRule(e);
03959 else {
03960 Proof pf;
03961 if(withProof())
03962 pf = newPf("rewrite_leaves_const", e);
03963 return newRWTheorem(e, res, Assumptions::emptyAssump(), pf);
03964 }
03965 }