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
00031
00032
00033
00034
00035
00036
00037
00038 #define _CVCL_TRUSTED_
00039
00040 #include "arith_theorem_producer.h"
00041 #include "theory_core.h"
00042
00043 using namespace std;
00044 using namespace CVCL;
00045
00046
00047
00048
00049
00050 ArithProofRules* TheoryArith::createProofRules() {
00051 return new ArithTheoremProducer(theoryCore()->getTM(), this);
00052 }
00053
00054
00055
00056
00057
00058
00059 #define CLASS_NAME "ArithTheoremProducer"
00060
00061
00062
00063 Theorem ArithTheoremProducer::uMinusToMult(const Expr& e) {
00064 Assumptions a;
00065 Proof pf;
00066 if(withProof()) pf = newPf("uminus_to_mult", e);
00067 return newRWTheorem((-e), (rat(-1) * e), a, pf);
00068 }
00069
00070
00071
00072 Theorem ArithTheoremProducer::minusToPlus(const Expr& x, const Expr& y)
00073 {
00074 Assumptions a;
00075 Proof pf;
00076 if(withProof()) pf = newPf("minus_to_plus", x, y);
00077 return newRWTheorem((x-y), (x + (rat(-1) * y)), a, pf);
00078 }
00079
00080
00081
00082
00083 Theorem ArithTheoremProducer::canonUMinusToDivide(const Expr& e) {
00084 Assumptions a;
00085 Proof pf;
00086 if(withProof()) pf = newPf("canon_uminus", e);
00087 return newRWTheorem((-e), (e / rat(-1)), a, pf);
00088 }
00089
00090
00091
00092
00093 Theorem ArithTheoremProducer::canonDivideConst(const Expr& c,
00094 const Expr& d) {
00095
00096 if(CHECK_PROOFS) {
00097 CHECK_SOUND(isRational(c),
00098 CLASS_NAME "::canonDivideConst:\n c not a constant: "
00099 + c.toString());
00100 CHECK_SOUND(isRational(d),
00101 CLASS_NAME "::canonDivideConst:\n d not a constant: "
00102 + d.toString());
00103 }
00104 Assumptions a;
00105 Proof pf;
00106 if(withProof())
00107 pf = newPf("canon_divide_const", c, d, d_hole);
00108 const Rational& dr = d.getRational();
00109 return newRWTheorem((c/d), (rat(dr==0? 0 : (c.getRational()/dr))), a, pf);
00110 }
00111
00112
00113 Theorem ArithTheoremProducer::canonDivideMult(const Expr& cx,
00114 const Expr& d) {
00115
00116 if(CHECK_PROOFS) {
00117 CHECK_SOUND(isMult(cx) && isRational(cx[0]),
00118 CLASS_NAME "::canonDivideMult:\n "
00119 "Not a (c * x) expression: "
00120 + cx.toString());
00121 CHECK_SOUND(isRational(d),
00122 CLASS_NAME "::canonDivideMult:\n "
00123 "d is not a constant: " + d.toString());
00124 }
00125 const Rational& dr = d.getRational();
00126 Rational cdr(dr==0? 0 : (cx[0].getRational()/dr));
00127 Expr cd(rat(cdr));
00128 Assumptions a;
00129 Proof pf;
00130 if(withProof())
00131 pf = newPf("canon_divide_mult", cx[0], cx[1], d);
00132
00133 if(cdr == 1)
00134 return newRWTheorem((cx/d), (cx[1]), a, pf);
00135 else if(cdr == 0)
00136 return newRWTheorem((cx/d), cd, a, pf);
00137 else
00138 return newRWTheorem((cx/d), (cd*cx[1]), a, pf);
00139 }
00140
00141
00142 Theorem ArithTheoremProducer::canonDividePlus(const Expr& sum, const Expr& d) {
00143 if(CHECK_PROOFS) {
00144 CHECK_SOUND(isPlus(sum) && sum.arity() >= 2 && isRational(sum[0]),
00145 CLASS_NAME "::canonUMinusPlus:\n "
00146 "Expr is not a canonical sum: "
00147 + sum.toString());
00148 CHECK_SOUND(isRational(d),
00149 CLASS_NAME "::canonUMinusPlus:\n "
00150 "d is not a const: " + d.toString());
00151 }
00152
00153 Assumptions a;
00154 Proof pf;
00155 if(withProof())
00156 pf = newPf("canon_divide_plus", rat(sum.arity()),
00157 sum.begin(), sum.end());
00158 vector<Expr> newKids;
00159 for(Expr::iterator i=sum.begin(), iend=sum.end(); i!=iend; ++i)
00160 newKids.push_back((*i)/d);
00161
00162 return newRWTheorem((sum/d), (plusExpr(newKids)), a, pf);
00163 }
00164
00165
00166 Theorem ArithTheoremProducer::canonDivideVar(const Expr& e, const Expr& d) {
00167 if(CHECK_PROOFS) {
00168 CHECK_SOUND(isRational(d),
00169 CLASS_NAME "::canonDivideVar:\n "
00170 "d is not a const: " + d.toString());
00171 }
00172 Assumptions a;
00173 Proof pf;
00174
00175 if(withProof())
00176 pf = newPf("canon_divide_var", e);
00177
00178 const Rational& dr = d.getRational();
00179 if(dr == 1)
00180 return newRWTheorem(e/d, e, a, pf);
00181 if(dr == 0)
00182 return newRWTheorem(e/d, d, a, pf);
00183 else
00184 return newRWTheorem(e/d, rat(1/dr) * e, a, pf);
00185 }
00186
00187
00188
00189
00190
00191
00192
00193
00194
00195
00196
00197
00198
00199
00200
00201
00202 Expr ArithTheoremProducer::simplifiedMultExpr(std::vector<Expr> & mulKids)
00203 {
00204 DebugAssert(mulKids.size() >= 1 && mulKids[0].isRational(), "");
00205 if (mulKids.size() == 1) {
00206 return mulKids[0];
00207 }
00208 if ((mulKids[0] == rat(1)) && mulKids.size() == 2) {
00209 return mulKids[1];
00210 }
00211 else
00212 return multExpr(mulKids);
00213 }
00214
00215 Expr ArithTheoremProducer::canonMultConstMult(const Expr & c,
00216 const Expr & e)
00217 {
00218
00219
00220
00221 DebugAssert(c.isRational() && e.getKind() == MULT, "");
00222 std::vector<Expr> mulKids;
00223 DebugAssert ((e.arity() > 1) && (e[0].isRational()),
00224 "arith_theorem_producer::canonMultConstMult: "
00225 "a canonized MULT expression must have arity "
00226 "greater than 1: and first child must be "
00227 "rational " + e.toString());
00228 Expr::iterator i = e.begin();
00229 mulKids.push_back(rat(c.getRational() * (*i).getRational()));
00230 ++i;
00231 for(; i != e.end(); ++i) {
00232 mulKids.push_back(*i);
00233 }
00234 return simplifiedMultExpr(mulKids);
00235 }
00236
00237 Expr ArithTheoremProducer::canonMultConstPlus(const Expr & e1,
00238 const Expr & e2)
00239 {
00240 DebugAssert(e1.isRational() && e2.getKind() == PLUS &&
00241 e2.arity() > 0, "");
00242
00243
00244
00245 std::vector<Theorem> thmPlusVector;
00246 Expr::iterator i = e2.begin();
00247 for(; i!= e2.end(); ++i) {
00248 thmPlusVector.push_back(canonMultMtermMterm(e1*(*i)));
00249 }
00250
00251 Theorem thmPlus1 =
00252 d_theoryArith->substitutivityRule(e2.getOp(), thmPlusVector);
00253 return thmPlus1.getRHS();
00254 }
00255
00256 Expr ArithTheoremProducer::canonMultPowPow(const Expr & e1,
00257 const Expr & e2)
00258 {
00259 DebugAssert(e1.getKind() == POW && e2.getKind() == POW, "");
00260
00261 Expr leaf1 = e1[1];
00262 Expr leaf2 = e2[1];
00263 Expr can_expr;
00264 if (leaf1 == leaf2) {
00265 Rational rsum = e1[0].getRational() + e2[0].getRational();
00266 if (rsum == 0) {
00267 return rat(1);
00268 }
00269 else if (rsum == 1) {
00270 return leaf1;
00271 }
00272 else
00273 {
00274 return powExpr(rat(rsum), leaf1);
00275 }
00276 }
00277 else
00278 {
00279 std::vector<Expr> mulKids;
00280 mulKids.push_back(rat(1));
00281
00282 if (leaf1 < leaf2) {
00283 mulKids.push_back(e2);
00284 mulKids.push_back(e1);
00285 }
00286 else
00287 {
00288 mulKids.push_back(e1);
00289 mulKids.push_back(e2);
00290 }
00291
00292 return simplifiedMultExpr(mulKids);
00293 }
00294 }
00295
00296 Expr ArithTheoremProducer::canonMultPowLeaf(const Expr & e1,
00297 const Expr & e2)
00298 {
00299 DebugAssert(e1.getKind() == POW, "");
00300
00301 Expr leaf1 = e1[1];
00302 Expr leaf2 = e2;
00303 Expr can_expr;
00304 if (leaf1 == leaf2) {
00305 Rational rsum = e1[0].getRational() + 1;
00306 if (rsum == 0) {
00307 return rat(1);
00308 }
00309 else if (rsum == 1) {
00310 return leaf1;
00311 }
00312 else
00313 {
00314 return powExpr(rat(rsum), leaf1);
00315 }
00316 }
00317 else
00318 {
00319 std::vector<Expr> mulKids;
00320 mulKids.push_back(rat(1));
00321
00322 if (leaf1 < leaf2) {
00323 mulKids.push_back(e2);
00324 mulKids.push_back(e1);
00325 }
00326 else
00327 {
00328 mulKids.push_back(e1);
00329 mulKids.push_back(e2);
00330 }
00331 return simplifiedMultExpr(mulKids);
00332 }
00333 }
00334
00335 Expr ArithTheoremProducer::canonMultLeafLeaf(const Expr & e1,
00336 const Expr & e2)
00337 {
00338
00339 Expr leaf1 = e1;
00340 Expr leaf2 = e2;
00341 Expr can_expr;
00342 if (leaf1 == leaf2) {
00343 return powExpr(rat(2), leaf1);
00344 }
00345 else
00346 {
00347 std::vector<Expr> mulKids;
00348 mulKids.push_back(rat(1));
00349
00350 if (leaf1 < leaf2) {
00351 mulKids.push_back(e2);
00352 mulKids.push_back(e1);
00353 }
00354 else
00355 {
00356 mulKids.push_back(e1);
00357 mulKids.push_back(e2);
00358 }
00359 return simplifiedMultExpr(mulKids);
00360 }
00361 }
00362
00363 Expr ArithTheoremProducer::canonMultLeafOrPowMult(const Expr & e1,
00364 const Expr & e2)
00365 {
00366 DebugAssert(e2.getKind() == MULT, "");
00367
00368
00369
00370
00371 Expr leaf1 = e1.getKind() == POW ? e1[1] : e1;
00372 std::vector<Expr> mulKids;
00373 DebugAssert(e2.arity() > 1, "MULT expr must have arity 2 or more");
00374 Expr::iterator i = e2.begin();
00375
00376 mulKids.push_back(*i);
00377 ++i;
00378
00379 for(; i != e2.end(); ++i) {
00380 Expr leaf2 = ((*i).getKind() == POW) ? (*i)[1] : (*i);
00381 if (leaf1 == leaf2) {
00382 Rational r1 = e1.getKind() == POW ? e1[0].getRational() : 1;
00383 Rational r2 =
00384 ((*i).getKind() == POW ? (*i)[0].getRational() : 1);
00385
00386
00387 if (r1 + r2 != 0) {
00388 if (r1 + r2 == 1) {
00389 mulKids.push_back(leaf1);
00390 }
00391 else
00392 {
00393 mulKids.push_back(powExpr(rat(r1 + r2), leaf1));
00394 }
00395 }
00396 break;
00397 }
00398
00399
00400
00401
00402 else if (leaf2 < leaf1) {
00403 mulKids.push_back(e1);
00404 mulKids.push_back(*i);
00405 break;
00406 }
00407 else
00408 mulKids.push_back(*i);
00409 }
00410 if (i == e2.end()) {
00411 mulKids.push_back(e1);
00412 }
00413 else
00414 {
00415
00416 for (++i; i != e2.end(); ++i) {
00417 mulKids.push_back(*i);
00418 }
00419 }
00420 return simplifiedMultExpr(mulKids);
00421 }
00422
00423
00424
00425 class MonomialLess {
00426 public:
00427 bool operator()(const Expr& e1, const Expr& e2) const {
00428 return ArithTheoremProducer::greaterthan(e1,e2);
00429 }
00430 };
00431
00432 typedef map<Expr,Rational,MonomialLess> MonomMap;
00433
00434 Expr
00435 ArithTheoremProducer::canonCombineLikeTerms(const std::vector<Expr> & sumExprs)
00436 {
00437 Rational constant = 0;
00438 MonomMap sumHashMap;
00439 vector<Expr> sumKids;
00440
00441
00442
00443 std::vector<Expr>::const_iterator i = sumExprs.begin();
00444 for (; i != sumExprs.end(); ++i) {
00445 Expr mul = *i;
00446 if (mul.isRational()) {
00447 constant = constant + mul.getRational();
00448 }
00449 else {
00450 switch (mul.getKind()) {
00451 case MULT: {
00452 std::vector<Expr> mulKids;
00453 DebugAssert(mul.arity() > 1 && mul[0].isRational(),"");
00454 mulKids.push_back(rat(1));
00455 Expr::iterator j = mul.begin();
00456 ++j;
00457 for (; j!= mul.end(); ++j) {
00458 mulKids.push_back(*j);
00459 }
00460
00461
00462 Expr tempExpr = mulKids.size() > 2 ? multExpr(mulKids): mulKids[1];
00463 MonomMap::iterator i=sumHashMap.find(tempExpr);
00464 if (i == sumHashMap.end()) {
00465 sumHashMap[tempExpr] = mul[0].getRational();
00466 }
00467 else {
00468 (*i).second += mul[0].getRational();
00469 }
00470 }
00471 break;
00472 default: {
00473 MonomMap::iterator i=sumHashMap.find(mul);
00474
00475 if (i == sumHashMap.end()) {
00476 sumHashMap[mul] = 1;
00477 }
00478 else {
00479 (*i).second += 1;
00480 }
00481 break;
00482 }
00483 }
00484 }
00485 }
00486
00487 sumKids.push_back(rat(constant));
00488 MonomMap::iterator j = sumHashMap.begin(), jend=sumHashMap.end();
00489 for(; j != jend; ++j) {
00490 if ((*j).second != 0)
00491 sumKids.push_back
00492 (canonMultMtermMterm(rat((*j).second) * (*j).first).getRHS());
00493 }
00494
00495
00496
00497
00498
00499
00500
00501
00502
00503
00504
00505
00506 if ((constant == 0) && (sumKids.size() == 2)) {
00507 return sumKids[1];
00508 }
00509 else if (sumKids.size() == 1) {
00510 return sumKids[0];
00511 }
00512 else
00513 return plusExpr(sumKids);
00514 }
00515
00516 Expr ArithTheoremProducer::canonMultLeafOrPowOrMultPlus(const Expr & e1,
00517 const Expr & e2)
00518 {
00519 DebugAssert(e2.getKind() == PLUS, "");
00520
00521
00522
00523
00524
00525
00526 std::vector<Expr> sumExprs;
00527
00528 Expr::iterator i = e2.begin();
00529 for (; i != e2.end(); ++i) {
00530 sumExprs.push_back(canonMultMtermMterm(e1 * (*i)).getRHS());
00531 }
00532 return canonCombineLikeTerms(sumExprs);
00533 }
00534
00535 Expr ArithTheoremProducer::canonMultPlusPlus(const Expr & e1,
00536 const Expr & e2)
00537 {
00538 DebugAssert(e1.getKind() == PLUS && e2.getKind() == PLUS, "");
00539
00540
00541
00542 std::vector<Expr> sumExprs;
00543
00544 Expr::iterator i = e1.begin();
00545 for (; i != e1.end(); ++i) {
00546 Expr::iterator j = e2.begin();
00547 for (; j != e2.end(); ++j) {
00548 sumExprs.push_back(canonMultMtermMterm((*i) * (*j)).getRHS());
00549 }
00550 }
00551 return canonCombineLikeTerms(sumExprs);
00552 }
00553
00554
00555
00556
00557
00558 Theorem
00559 ArithTheoremProducer::canonMultMtermMterm(const Expr& e)
00560 {
00561 if(CHECK_PROOFS) {
00562 CHECK_SOUND(isMult(e) && e.arity() == 2,
00563 "canonMultMtermMterm: e = "+e.toString());
00564 }
00565 Assumptions a;
00566 Proof pf;
00567 Expr rhs;
00568 const Expr& e1 = e[0];
00569 const Expr& e2 = e[1];
00570 string cmmm = "canon_mult_mterm_mterm";
00571
00572 if (e1.isRational()) {
00573
00574 const Rational& c = e1.getRational();
00575 if (c == 0)
00576 return canonMultZero(e2);
00577 else if (c == 1)
00578 return canonMultOne(e2);
00579 else {
00580 switch (e2.getKind()) {
00581 case RATIONAL_EXPR :
00582
00583 return canonMultConstConst(e1,e2);
00584 break;
00585
00586 case POW:
00587
00588
00589 return d_theoryArith->reflexivityRule (e);
00590
00591 break;
00592 case MULT:
00593 rhs = canonMultConstMult(e1,e2);
00594 if(withProof()) pf = newPf(cmmm,e,rhs);
00595 return newRWTheorem(e, rhs, a, pf);
00596 break;
00597 case PLUS:
00598 rhs = canonMultConstPlus(e1,e2);
00599 if(withProof()) pf = newPf(cmmm,e,rhs);
00600 return newRWTheorem(e, rhs, a, pf);
00601 break;
00602 default:
00603
00604
00605 return d_theoryArith->reflexivityRule(e);
00606 break;
00607 }
00608 }
00609 }
00610 else if (e1.getKind() == POW) {
00611 switch (e2.getKind()) {
00612 case RATIONAL_EXPR:
00613
00614 return canonMultMtermMterm(e2 * e1);
00615 break;
00616 case POW:
00617 rhs = canonMultPowPow(e1,e2);
00618 if(withProof()) pf = newPf(cmmm,e,rhs);
00619 return newRWTheorem(e,rhs, a, pf);
00620 break;
00621 case MULT:
00622 rhs = canonMultLeafOrPowMult(e1,e2);
00623 if(withProof()) pf = newPf(cmmm,e,rhs);
00624 return newRWTheorem(e, rhs, a, pf);
00625 break;
00626 case PLUS:
00627 rhs = canonMultLeafOrPowOrMultPlus(e1,e2);
00628 if(withProof()) pf = newPf(cmmm,e,rhs);
00629 return newRWTheorem(e, rhs, a, pf);
00630 break;
00631 default:
00632 rhs = canonMultPowLeaf(e1,e2);
00633 if(withProof()) pf = newPf(cmmm,e,rhs);
00634 return newRWTheorem(e,rhs, a, pf);
00635 break;
00636 }
00637 }
00638 else if (e1.getKind() == MULT) {
00639 switch (e2.getKind()) {
00640 case RATIONAL_EXPR:
00641 case POW:
00642
00643 return canonMultMtermMterm(e2 * e1);
00644 break;
00645 case MULT:
00646 {
00647
00648 Expr result = e2;
00649 Expr::iterator i = e1.begin();
00650 for (; i != e1.end(); ++i) {
00651 result = canonMultMtermMterm((*i) * result).getRHS();
00652 }
00653 if(withProof()) pf = newPf(cmmm,e,result);
00654 return newRWTheorem(e, result, a, pf);
00655 }
00656 break;
00657 case PLUS:
00658 rhs = canonMultLeafOrPowOrMultPlus(e1,e2);
00659 if(withProof()) pf = newPf(cmmm,e,rhs);
00660 return newRWTheorem(e,rhs, a, pf);
00661 break;
00662 default:
00663
00664
00665 return canonMultMtermMterm(e2 * e1);
00666 break;
00667 }
00668 }
00669 else if (e1.getKind() == PLUS) {
00670 switch (e2.getKind()) {
00671 case RATIONAL_EXPR:
00672 case POW:
00673 case MULT:
00674
00675 return canonMultMtermMterm(e2 * e1);
00676 break;
00677 case PLUS:
00678 rhs = canonMultPlusPlus(e1,e2);
00679 if(withProof()) pf = newPf(cmmm,e,rhs);
00680 return newRWTheorem(e, rhs, a, pf);
00681 break;
00682 default:
00683
00684
00685 return canonMultMtermMterm(e2 * e1);
00686 break;
00687 }
00688 }
00689 else {
00690
00691 switch (e2.getKind()) {
00692 case RATIONAL_EXPR:
00693
00694 return canonMultMtermMterm(e2 * e1);
00695 break;
00696 case POW:
00697 rhs = canonMultPowLeaf(e2,e1);
00698 if(withProof()) pf = newPf(cmmm,e,rhs);
00699 return newRWTheorem(e, rhs, a, pf);
00700 break;
00701 case MULT:
00702 rhs = canonMultLeafOrPowMult(e1,e2);;
00703 if(withProof()) pf = newPf(cmmm,e,rhs);
00704 return newRWTheorem(e, rhs, a, pf);
00705 break;
00706 case PLUS:
00707 rhs = canonMultLeafOrPowOrMultPlus(e1,e2);
00708 if(withProof()) pf = newPf(cmmm,e,rhs);
00709 return newRWTheorem(e, rhs, a, pf);
00710 break;
00711 default:
00712
00713 rhs = canonMultLeafLeaf(e1,e2);
00714 if(withProof()) pf = newPf(cmmm,e,rhs);
00715 return newRWTheorem(e, rhs, a, pf);
00716 break;
00717 }
00718 }
00719 FatalAssert(false, "Unreachable");
00720 return newRWTheorem(e, rhs, a, pf);
00721 }
00722
00723
00724 Theorem
00725 ArithTheoremProducer::canonPlus(const Expr& e)
00726 {
00727 Assumptions a;
00728 Proof pf;
00729
00730 if (withProof()) {
00731 pf = newPf("canon_plus", e);
00732 }
00733 DebugAssert(e.getKind() == PLUS, "");
00734
00735
00736
00737 std::vector<Expr> sumKids;
00738 Expr::iterator i = e.begin();
00739 for(; i != e.end(); ++i) {
00740 if ((*i).getKind() != PLUS) {
00741 sumKids.push_back(*i);
00742 }
00743 else
00744 {
00745 Expr::iterator j = (*i).begin();
00746 for(; j != (*i).end(); ++j)
00747 sumKids.push_back(*j);
00748 }
00749 }
00750 Expr val = canonCombineLikeTerms(sumKids);
00751 if (withProof()) {
00752 pf = newPf("canon_plus", e, val);
00753 }
00754 return newRWTheorem(e, val, a, pf);
00755 }
00756
00757
00758 Theorem
00759 ArithTheoremProducer::canonMult(const Expr& e)
00760 {
00761 Assumptions a;
00762 Proof pf;
00763 DebugAssert(e.getKind() == MULT && e.arity() > 1, "");
00764 Expr::iterator i = e.begin();
00765 Expr result = *i;
00766 ++i;
00767 for (; i != e.end(); ++i) {
00768 result = canonMultMtermMterm(result * (*i)).getRHS();
00769 }
00770 if (withProof()) {
00771 pf = newPf("canon_mult", e,result);
00772 }
00773 return newRWTheorem(e, result, a, pf);
00774 }
00775
00776
00777 Theorem
00778 ArithTheoremProducer::canonInvertConst(const Expr& e)
00779 {
00780 if(CHECK_PROOFS)
00781 CHECK_SOUND(isRational(e), "expecting a rational: e = "+e.toString());
00782
00783 Assumptions a;
00784 Proof pf;
00785
00786 if (withProof()) {
00787 pf = newPf("canon_invert_const", e);
00788 }
00789 const Rational& er = e.getRational();
00790 return newRWTheorem((rat(1)/e), rat(er==0? 0 : (1/er)), a, pf);
00791 }
00792
00793
00794 Theorem
00795 ArithTheoremProducer::canonInvertLeaf(const Expr& e)
00796 {
00797 Assumptions a;
00798 Proof pf;
00799
00800 if (withProof()) {
00801 pf = newPf("canon_invert_leaf", e);
00802 }
00803 return newRWTheorem((rat(1)/e), powExpr(rat(-1), e), a, pf);
00804 }
00805
00806
00807 Theorem
00808 ArithTheoremProducer::canonInvertPow(const Expr& e)
00809 {
00810 DebugAssert(e.getKind() == POW, "expecting a rational"+e[0].toString());
00811
00812 Assumptions a;
00813 Proof pf;
00814
00815 if (withProof()) {
00816 pf = newPf("canon_invert_pow", e);
00817 }
00818 if (e[0].getRational() == -1)
00819 return newRWTheorem((rat(1)/e), e[1], a, pf);
00820 else
00821 return newRWTheorem((rat(1)/e),
00822 powExpr(rat(-e[0].getRational()), e),
00823 a,
00824 pf);
00825 }
00826
00827 Theorem
00828 ArithTheoremProducer::canonInvertMult(const Expr& e)
00829 {
00830 DebugAssert(e.getKind() == MULT, "expecting a rational"+e[0].toString());
00831
00832 Assumptions a;
00833 Proof pf;
00834
00835 if (withProof()) {
00836 pf = newPf("canon_invert_mult", e);
00837 }
00838
00839 DebugAssert(e.arity() > 1, "MULT should have arity > 1"+e.toString());
00840 Expr result = canonInvert(e[0]).getRHS();
00841 for (int i = 1; i < e.arity(); ++i) {
00842 result =
00843 canonMultMtermMterm(result * canonInvert(e[i]).getRHS()).getRHS();
00844 }
00845 return newRWTheorem((rat(1)/e), result, a, pf);
00846 }
00847
00848
00849
00850
00851 Theorem
00852 ArithTheoremProducer::canonInvert(const Expr& e)
00853 {
00854 DebugAssert(e.getKind() != PLUS,
00855 "Cannot do inverse on a PLUS"+e.toString());
00856 switch (e.getKind()) {
00857 case RATIONAL_EXPR:
00858 return canonInvertConst(e);
00859 break;
00860 case POW:
00861 return canonInvertPow(e);
00862 break;
00863 case MULT:
00864 return canonInvertMult(e);
00865 break;
00866 default:
00867
00868 return canonInvertLeaf(e);
00869 break;
00870 }
00871 }
00872
00873
00874 Theorem
00875 ArithTheoremProducer::canonDivide(const Expr& e)
00876 {
00877 DebugAssert(e.getKind() == DIVIDE, "Expecting Divide"+e.toString());
00878 Assumptions a;
00879 Proof pf;
00880
00881 if (withProof()) {
00882 pf = newPf("canon_invert_divide", e);
00883 }
00884
00885 Theorem thm = newRWTheorem(e, e[0]*(canonInvert(e[1]).getRHS()), a, pf);
00886
00887 return d_theoryArith->transitivityRule(thm, canonMult(thm.getRHS()));
00888 }
00889
00890
00891
00892
00893 Theorem
00894 ArithTheoremProducer::canonMultTermConst(const Expr& c, const Expr& t) {
00895 Assumptions a;
00896 Proof pf;
00897 if(CHECK_PROOFS) {
00898 CHECK_SOUND(isRational(c),
00899 CLASS_NAME "::canonMultTermConst:\n "
00900 "c is not a constant: " + c.toString());
00901 }
00902 if(withProof()) pf = newPf("canon_mult_term_const", c, t);
00903 return newRWTheorem((t*c), (c*t), a, pf);
00904 }
00905
00906
00907
00908 Theorem
00909 ArithTheoremProducer::canonMultTerm1Term2(const Expr& t1, const Expr& t2) {
00910
00911
00912
00913 if(CHECK_PROOFS) {
00914 CHECK_SOUND(false, "Fatal Error: We don' support multiplication"
00915 "of two non constant terms at this time "
00916 + t1.toString() + " and " + t2.toString());
00917 }
00918 return Theorem();
00919 }
00920
00921
00922
00923 Theorem ArithTheoremProducer::canonMultZero(const Expr& e) {
00924 Assumptions a;
00925 Proof pf;
00926 if(withProof()) pf = newPf("canon_mult_zero", e);
00927 return newRWTheorem((rat(0)*e), rat(0), a, pf);
00928 }
00929
00930
00931
00932 Theorem ArithTheoremProducer::canonMultOne(const Expr& e) {
00933 Assumptions a;
00934 Proof pf;
00935 if(withProof()) pf = newPf("canon_mult_one", e);
00936 return newRWTheorem((rat(1)*e), e, a, pf);
00937 }
00938
00939
00940
00941 Theorem
00942 ArithTheoremProducer::canonMultConstConst(const Expr& c1, const Expr& c2) {
00943 Assumptions a;
00944 Proof pf;
00945 if(CHECK_PROOFS) {
00946 CHECK_SOUND(isRational(c1),
00947 CLASS_NAME "::canonMultConstConst:\n "
00948 "c1 is not a constant: " + c1.toString());
00949 CHECK_SOUND(isRational(c2),
00950 CLASS_NAME "::canonMultConstConst:\n "
00951 "c2 is not a constant: " + c2.toString());
00952 }
00953 if(withProof()) pf = newPf("canon_mult_const_const", c1, c2);
00954 return
00955 newRWTheorem((c1*c2), rat(c1.getRational()*c2.getRational()), a, pf);
00956 }
00957
00958
00959
00960 Theorem
00961 ArithTheoremProducer::canonMultConstTerm(const Expr& c1,
00962 const Expr& c2,const Expr& t) {
00963 Assumptions a;
00964 Proof pf;
00965 if(CHECK_PROOFS) {
00966 CHECK_SOUND(isRational(c1),
00967 CLASS_NAME "::canonMultConstTerm:\n "
00968 "c1 is not a constant: " + c1.toString());
00969 CHECK_SOUND(isRational(c2),
00970 CLASS_NAME "::canonMultConstTerm:\n "
00971 "c2 is not a constant: " + c2.toString());
00972 }
00973
00974 if(withProof()) pf = newPf("canon_mult_const_term", c1, c2, t);
00975 return
00976 newRWTheorem(c1*(c2*t), rat(c1.getRational()*c2.getRational())*t, a, pf);
00977 }
00978
00979
00980
00981 Theorem
00982 ArithTheoremProducer::canonMultConstSum(const Expr& c1, const Expr& sum) {
00983 Assumptions a;
00984 Proof pf;
00985 std::vector<Expr> sumKids;
00986
00987 if(CHECK_PROOFS) {
00988 CHECK_SOUND(isRational(c1),
00989 CLASS_NAME "::canonMultConstTerm:\n "
00990 "c1 is not a constant: " + c1.toString());
00991 CHECK_SOUND(PLUS == sum.getKind(),
00992 CLASS_NAME "::canonMultConstTerm:\n "
00993 "the kind must be a PLUS: " + sum.toString());
00994 }
00995 Expr::iterator i = sum.begin();
00996 for(; i != sum.end(); ++i)
00997 sumKids.push_back(c1*(*i));
00998 Expr ret = plusExpr(sumKids);
00999 if(withProof()) pf = newPf("canon_mult_const_sum", c1, sum, ret);
01000 return newRWTheorem((c1*sum),ret , a, pf);
01001 }
01002
01003
01004
01005 Theorem
01006 ArithTheoremProducer::canonPowConst(const Expr& e) {
01007 if(CHECK_PROOFS) {
01008 CHECK_SOUND(e.getKind() == POW && e.arity() == 2
01009 && e[0].isRational() && e[1].isRational(),
01010 "ArithTheoremProducer::canonPowConst("+e.toString()+")");
01011 }
01012 const Rational& p = e[0].getRational();
01013 const Rational& base = e[1].getRational();
01014 if(CHECK_PROOFS) {
01015 CHECK_SOUND(p.isInteger(),
01016 "ArithTheoremProducer::canonPowConst("+e.toString()+")");
01017 }
01018 Assumptions a;
01019 Proof pf;
01020 if(withProof())
01021 pf = newPf("canon_pow_const", e);
01022 return newRWTheorem(e, rat(pow(p, base)), a, pf);
01023 }
01024
01025
01026
01027
01028 Theorem
01029 ArithTheoremProducer::canonFlattenSum(const Expr& e) {
01030 Assumptions a;
01031 Proof pf;
01032 std::vector<Expr> sumKids;
01033 if(CHECK_PROOFS) {
01034 CHECK_SOUND(PLUS == e.getKind(),
01035 CLASS_NAME "::canonFlattenSum:\n"
01036 "input must be a PLUS:" + e.toString());
01037 }
01038
01039 Expr::iterator i = e.begin();
01040 for(; i != e.end(); ++i){
01041 if (PLUS != (*i).getKind())
01042 sumKids.push_back(*i);
01043 else {
01044 Expr::iterator j = (*i).begin();
01045 for(; j != (*i).end(); ++j)
01046 sumKids.push_back(*j);
01047 }
01048 }
01049 Expr ret = plusExpr(sumKids);
01050 if(withProof()) pf = newPf("canon_flatten_sum", e,ret);
01051 return newRWTheorem(e,ret, a, pf);
01052 }
01053
01054
01055
01056 Theorem
01057 ArithTheoremProducer::canonComboLikeTerms(const Expr& e) {
01058 Assumptions a;
01059 Proof pf;
01060 std::vector<Expr> sumKids;
01061 ExprMap<Rational> sumHashMap;
01062 Rational constant = 0;
01063
01064 if(CHECK_PROOFS) {
01065 Expr::iterator k = e.begin();
01066 for(; k != e.end(); ++k)
01067 CHECK_SOUND(!isPlus(*k),
01068 CLASS_NAME "::canonComboLikeTerms:\n"
01069 "input must be a flattened PLUS:" + k->toString());
01070 }
01071 Expr::iterator i = e.begin();
01072 for(; i != e.end(); ++i){
01073 if(i->isRational())
01074 constant = constant + i->getRational();
01075 else {
01076 if (!isMult(*i)) {
01077 if(0 == sumHashMap.count((*i)))
01078 sumHashMap[*i] = 1;
01079 else
01080 sumHashMap[*i] += 1;
01081 }
01082 else {
01083 if(0 == sumHashMap.count((*i)[1]))
01084 sumHashMap[(*i)[1]] = (*i)[0].getRational();
01085 else
01086 sumHashMap[(*i)[1]] = sumHashMap[(*i)[1]] + (*i)[0].getRational();
01087 }
01088 }
01089 }
01090
01091 sumKids.push_back(rat(constant));
01092 ExprMap<Rational>::iterator j = sumHashMap.begin();
01093 for(; j != sumHashMap.end(); ++j) {
01094 if(0 == (*j).second)
01095 ;
01096 else if (1 == (*j).second)
01097 sumKids.push_back((*j).first);
01098 else
01099 sumKids.push_back(rat((*j).second) * (*j).first);
01100 }
01101
01102
01103
01104
01105 Expr ret;
01106 if(2 == sumKids.size() && 0 == constant) ret = sumKids[1];
01107 else if (1 == sumKids.size()) ret = sumKids[0];
01108 else ret = plusExpr(sumKids);
01109
01110 if(withProof()) pf = newPf("canon_combo_like_terms",e,ret);
01111 return newRWTheorem(e, ret, a, pf);
01112 }
01113
01114
01115
01116
01117
01118
01119
01120 Theorem ArithTheoremProducer::constPredicate(const Expr& e) {
01121 if(CHECK_PROOFS) {
01122 CHECK_SOUND(e.arity() == 2 && isRational(e[0]) && isRational(e[1]),
01123 CLASS_NAME "::constPredicate:\n "
01124 "non-const parameters: " + e.toString());
01125 }
01126 Assumptions a;
01127 Proof pf;
01128 bool result(false);
01129 int kind = e.getKind();
01130 Rational r1 = e[0].getRational(), r2 = e[1].getRational();
01131 switch(kind) {
01132 case EQ:
01133 result = (r1 == r2)?true : false;
01134 break;
01135 case LT:
01136 result = (r1 < r2)?true : false;
01137 break;
01138 case LE:
01139 result = (r1 <= r2)?true : false;
01140 break;
01141 case GT:
01142 result = (r1 > r2)?true : false;
01143 break;
01144 case GE:
01145 result = (r1 >= r2)?true : false;
01146 break;
01147 default:
01148 if(CHECK_PROOFS) {
01149 CHECK_SOUND(false,
01150 "ArithTheoremProducer::constPredicate: wrong kind");
01151 }
01152 break;
01153 }
01154 Expr ret = (result) ? d_em->trueExpr() : d_em->falseExpr();
01155 if(withProof()) pf = newPf("const_predicate", e,ret);
01156 return newRWTheorem(e, ret, a, pf);
01157 }
01158
01159
01160 Theorem ArithTheoremProducer::rightMinusLeft(const Expr& e)
01161 {
01162 Assumptions a;
01163 Proof pf;
01164 int kind = e.getKind();
01165 if(CHECK_PROOFS) {
01166 CHECK_SOUND((EQ==kind) ||
01167 (LT==kind) ||
01168 (LE==kind) ||
01169 (GE==kind) ||
01170 (GT==kind),
01171 "ArithTheoremProduder::rightMinusLeft: wrong kind");
01172 }
01173 if(withProof()) pf = newPf("right_minus_left",e);
01174 return newRWTheorem(e, Expr(e.getOp(), rat(0), e[1] - e[0]), a, pf);
01175 }
01176
01177
01178
01179 Theorem ArithTheoremProducer::plusPredicate(const Expr& x,
01180 const Expr& y,
01181 const Expr& z, int kind) {
01182 if(CHECK_PROOFS) {
01183 CHECK_SOUND((EQ==kind) ||
01184 (LT==kind) ||
01185 (LE==kind) ||
01186 (GE==kind) ||
01187 (GT==kind),
01188 "ArithTheoremProduder::plusPredicate: wrong kind");
01189 }
01190 Assumptions a;
01191 Proof pf;
01192 Expr left = Expr(kind, x, y);
01193 Expr right = Expr(kind, x + z, y + z);
01194 if(withProof()) pf = newPf("plus_predicate",left,right);
01195 return newRWTheorem(left, right, a, pf);
01196 }
01197
01198
01199 Theorem ArithTheoremProducer::multEqn(const Expr& x,
01200 const Expr& y,
01201 const Expr& z) {
01202 Assumptions a;
01203 Proof pf;
01204 if(CHECK_PROOFS)
01205 CHECK_SOUND(z.isRational() && z.getRational() != 0,
01206 "ArithTheoremProducer::multEqn(): multiplying equation by 0");
01207 if(withProof()) pf = newPf("mult_eqn", x, y, z);
01208 return newRWTheorem(x.eqExpr(y), (x * z).eqExpr(y * z), a, pf);
01209 }
01210
01211
01212
01213
01214 Theorem ArithTheoremProducer::multIneqn(const Expr& e, const Expr& z)
01215 {
01216 int kind = e.getKind();
01217
01218 if(CHECK_PROOFS) {
01219 CHECK_SOUND((LT==kind) ||
01220 (LE==kind) ||
01221 (GE==kind) ||
01222 (GT==kind),
01223 "ArithTheoremProduder::multIneqn: wrong kind");
01224 CHECK_SOUND(z.isRational() && z.getRational() != 0,
01225 "ArithTheoremProduder::multIneqn: "
01226 "z must be non-zero rational: " + z.toString());
01227 }
01228 Op op(e.getOp());
01229 Assumptions a;
01230 Proof pf;
01231
01232 Expr ret;
01233 if(0 < z.getRational())
01234 ret = Expr(op, e[0]*z, e[1]*z);
01235 else
01236 ret = Expr(op, e[1]*z, e[0]*z);
01237 if(withProof()) pf = newPf("mult_ineqn", e, ret);
01238 return newRWTheorem(e, ret, a, pf);
01239 }
01240
01241
01242
01243 Theorem ArithTheoremProducer::flipInequality(const Expr& e)
01244 {
01245 Assumptions a;
01246 Proof pf;
01247 if(CHECK_PROOFS) {
01248 CHECK_SOUND(isGT(e) || isGE(e),
01249 "ArithTheoremProducer::flipInequality: wrong kind: " +
01250 e.toString());
01251 }
01252
01253 int kind = isGE(e) ? LE : LT;
01254 Expr ret = Expr(kind, e[1], e[0]);
01255 if(withProof()) pf = newPf("flip_inequality", e,ret);
01256 return newRWTheorem(e,ret, a, pf);
01257 }
01258
01259
01260
01261
01262
01263
01264 Theorem ArithTheoremProducer::negatedInequality(const Expr& e)
01265 {
01266 const Expr& ineq = e[0];
01267 if(CHECK_PROOFS) {
01268 CHECK_SOUND(e.isNot(),
01269 "ArithTheoremProducer::negatedInequality: wrong kind: " +
01270 e.toString());
01271 CHECK_SOUND(isIneq(ineq),
01272 "ArithTheoremProducer::negatedInequality: wrong kind: " +
01273 (ineq).toString());
01274 }
01275 Assumptions a;
01276 Proof pf;
01277 if(withProof()) pf = newPf("negated_inequality", e);
01278
01279 int kind;
01280
01281
01282
01283
01284 kind =
01285 isLT(ineq) ? GE :
01286 isLE(ineq) ? GT :
01287 isGT(ineq) ? LE :
01288 LT;
01289 return newRWTheorem(e, Expr(kind, ineq[0], ineq[1]), a, pf);
01290 }
01291
01292
01293
01294 Theorem ArithTheoremProducer::realShadow(const Theorem& alphaLTt,
01295 const Theorem& tLTbeta)
01296 {
01297 const Expr& expr1 = alphaLTt.getExpr();
01298 const Expr& expr2 = tLTbeta.getExpr();
01299 if(CHECK_PROOFS) {
01300 CHECK_SOUND((isLE(expr1) || isLT(expr1)) &&
01301 (isLE(expr2) || isLT(expr2)),
01302 "ArithTheoremProducer::realShadow: Wrong Kind: " +
01303 alphaLTt.toString() + tLTbeta.toString());
01304
01305 CHECK_SOUND(expr1[1] == expr2[0],
01306 "ArithTheoremProducer::realShadow:"
01307 " t must be same for both inputs: " +
01308 expr1[1].toString() + " , " + expr2[0].toString());
01309 }
01310 Assumptions a;
01311 if(withAssumptions()) {
01312 a = merge(alphaLTt, tLTbeta);
01313 }
01314 int firstKind = expr1.getKind();
01315 int secondKind = expr2.getKind();
01316 int kind = (firstKind == secondKind) ? firstKind : LT;
01317 Proof pf;
01318 if(withProof()) {
01319 vector<Proof> pfs;
01320 pfs.push_back(alphaLTt.getProof());
01321 pfs.push_back(tLTbeta.getProof());
01322 pf = newPf("real_shadow",expr1, expr2, pfs);
01323 }
01324 return newTheorem(Expr(kind, expr1[0], expr2[1]), a, pf);
01325 }
01326
01327
01328
01329
01330
01331
01332 Theorem ArithTheoremProducer::realShadowEq(const Theorem& alphaLEt,
01333 const Theorem& tLEalpha)
01334 {
01335 const Expr& expr1 = alphaLEt.getExpr();
01336 const Expr& expr2 = tLEalpha.getExpr();
01337 if(CHECK_PROOFS) {
01338 CHECK_SOUND(isLE(expr1) && isLE(expr2),
01339 "ArithTheoremProducer::realShadowLTLE: Wrong Kind: " +
01340 alphaLEt.toString() + tLEalpha.toString());
01341
01342 CHECK_SOUND(expr1[1] == expr2[0],
01343 "ArithTheoremProducer::realShadowLTLE:"
01344 " t must be same for both inputs: " +
01345 alphaLEt.toString() + " , " + tLEalpha.toString());
01346
01347 CHECK_SOUND(expr1[0] == expr2[1],
01348 "ArithTheoremProducer::realShadowLTLE:"
01349 " alpha must be same for both inputs: " +
01350 alphaLEt.toString() + " , " + tLEalpha.toString());
01351 }
01352 Assumptions a;
01353 if(withAssumptions()) {
01354 a = merge(alphaLEt, tLEalpha);
01355 }
01356 Proof pf;
01357 if(withProof()) {
01358 vector<Proof> pfs;
01359 pfs.push_back(alphaLEt.getProof());
01360 pfs.push_back(tLEalpha.getProof());
01361 pf = newPf("real_shadow_eq", alphaLEt.getExpr(), tLEalpha.getExpr(), pfs);
01362 }
01363 return newRWTheorem(expr1[0], expr1[1], a, pf);
01364 }
01365
01366 Theorem
01367 ArithTheoremProducer::finiteInterval(const Theorem& aLEt,
01368 const Theorem& tLEac,
01369 const Theorem& isInta,
01370 const Theorem& isIntt) {
01371 const Expr& e1 = aLEt.getExpr();
01372 const Expr& e2 = tLEac.getExpr();
01373 if(CHECK_PROOFS) {
01374 CHECK_SOUND(isLE(e1) && isLE(e2),
01375 "ArithTheoremProducer::finiteInterval:\n e1 = "
01376 +e1.toString()+"\n e2 = "+e2.toString());
01377
01378 CHECK_SOUND(e1[1] == e2[0],
01379 "ArithTheoremProducer::finiteInterval:\n e1 = "
01380 +e1.toString()+"\n e2 = "+e2.toString());
01381
01382 CHECK_SOUND(isPlus(e2[1]) && e2[1].arity() == 2,
01383 "ArithTheoremProducer::finiteInterval:\n e1 = "
01384 +e1.toString()+"\n e2 = "+e2.toString());
01385
01386 CHECK_SOUND(e1[0] == e2[1][0],
01387 "ArithTheoremProducer::finiteInterval:\n e1 = "
01388 +e1.toString()+"\n e2 = "+e2.toString());
01389
01390 CHECK_SOUND(e2[1][1].isRational() && e2[1][1].getRational().isInteger()
01391 && e2[1][1].getRational() >= 1,
01392 "ArithTheoremProducer::finiteInterval:\n e1 = "
01393 +e1.toString()+"\n e2 = "+e2.toString());
01394
01395 const Expr& isIntaExpr = isInta.getExpr();
01396 const Expr& isInttExpr = isIntt.getExpr();
01397 CHECK_SOUND(isIntPred(isIntaExpr) && isIntaExpr[0] == e1[0],
01398 "Wrong integrality constraint:\n e1 = "
01399 +e1.toString()+"\n isInta = "+isIntaExpr.toString());
01400 CHECK_SOUND(isIntPred(isInttExpr) && isInttExpr[0] == e1[1],
01401 "Wrong integrality constraint:\n e1 = "
01402 +e1.toString()+"\n isIntt = "+isInttExpr.toString());
01403 }
01404 Assumptions a;
01405 Proof pf;
01406 if(withAssumptions()) {
01407 vector<Theorem> thms;
01408 thms.push_back(aLEt);
01409 thms.push_back(tLEac);
01410 thms.push_back(isInta);
01411 thms.push_back(isIntt);
01412 a = merge(thms);
01413 }
01414 if(withProof()) {
01415 vector<Expr> es;
01416 vector<Proof> pfs;
01417 es.push_back(e1);
01418 es.push_back(e2);
01419 es.push_back(isInta.getExpr());
01420 es.push_back(isIntt.getExpr());
01421 pfs.push_back(aLEt.getProof());
01422 pfs.push_back(tLEac.getProof());
01423 pfs.push_back(isInta.getProof());
01424 pfs.push_back(isIntt.getProof());
01425 pf = newPf("finite_interval", es, pfs);
01426 }
01427
01428 Expr g(grayShadow(e1[1], e1[0], 0, e2[1][1].getRational()));
01429 return newTheorem(g, a, pf);
01430 }
01431
01432
01433
01434 Theorem ArithTheoremProducer::darkGrayShadow2ab(const Theorem& betaLEbx,
01435 const Theorem& axLEalpha,
01436 const Theorem& isIntAlpha,
01437 const Theorem& isIntBeta,
01438 const Theorem& isIntx) {
01439 const Expr& expr1 = betaLEbx.getExpr();
01440 const Expr& expr2 = axLEalpha.getExpr();
01441 const Expr& isIntAlphaExpr = isIntAlpha.getExpr();
01442 const Expr& isIntBetaExpr = isIntBeta.getExpr();
01443 const Expr& isIntxExpr = isIntx.getExpr();
01444
01445 if(CHECK_PROOFS) {
01446 CHECK_SOUND(isLE(expr1) && isLE(expr2),
01447 "ArithTheoremProducer::darkGrayShadow2ab: Wrong Kind: " +
01448 betaLEbx.toString() + axLEalpha.toString());
01449 }
01450
01451 const Expr& beta = expr1[0];
01452 const Expr& bx = expr1[1];
01453 const Expr& ax = expr2[0];
01454 const Expr& alpha = expr2[1];
01455 Rational a = isMult(ax)? ax[0].getRational() : 1;
01456 Rational b = isMult(bx)? bx[0].getRational() : 1;
01457 const Expr& x = isMult(ax)? ax[1] : ax;
01458
01459 if(CHECK_PROOFS) {
01460
01461 CHECK_SOUND(isIntPred(isIntAlphaExpr) && isIntAlphaExpr[0] == alpha,
01462 "ArithTheoremProducer::darkGrayShadow2ab:\n "
01463 "wrong integrality constraint:\n alpha = "
01464 +alpha.toString()+"\n isIntAlpha = "
01465 +isIntAlphaExpr.toString());
01466 CHECK_SOUND(isIntPred(isIntBetaExpr) && isIntBetaExpr[0] == beta,
01467 "ArithTheoremProducer::darkGrayShadow2ab:\n "
01468 "wrong integrality constraint:\n beta = "
01469 +beta.toString()+"\n isIntBeta = "
01470 +isIntBetaExpr.toString());
01471 CHECK_SOUND(isIntPred(isIntxExpr) && isIntxExpr[0] == x,
01472 "ArithTheoremProducer::darkGrayShadow2ab:\n "
01473 "wrong integrality constraint:\n x = "
01474 +x.toString()+"\n isIntx = "
01475 +isIntxExpr.toString());
01476
01477 CHECK_SOUND(!isMult(ax) || ax.arity() == 2,
01478 "ArithTheoremProducer::darkGrayShadow2ab:\n ax<=alpha: " +
01479 axLEalpha.toString());
01480 CHECK_SOUND(!isMult(bx) || (bx.arity() == 2 && bx[1] == x),
01481 "ArithTheoremProducer::darkGrayShadow2ab:\n beta<=bx: "
01482 +betaLEbx.toString()
01483 +"\n ax<=alpha: "+ axLEalpha.toString());
01484 CHECK_SOUND(1 <= a && a <= b && 2 <= b,
01485 "ArithTheoremProducer::darkGrayShadow2ab:\n beta<=bx: "
01486 +betaLEbx.toString()
01487 +"\n ax<=alpha: "+ axLEalpha.toString());
01488 }
01489 Assumptions A;
01490 if(withAssumptions()) {
01491 vector<Theorem> thms;
01492 thms.push_back(betaLEbx);
01493 thms.push_back(axLEalpha);
01494 thms.push_back(isIntAlpha);
01495 thms.push_back(isIntBeta);
01496 thms.push_back(isIntx);
01497 A = merge(thms);
01498 }
01499 Proof pf;
01500 if(withProof()) {
01501 vector<Proof> pfs;
01502 pfs.push_back(betaLEbx.getProof());
01503 pfs.push_back(axLEalpha.getProof());
01504 pfs.push_back(isIntAlpha.getProof());
01505 pfs.push_back(isIntBeta.getProof());
01506 pfs.push_back(isIntx.getProof());
01507
01508 pf = newPf("dark_grayshadow_2ab", expr1, expr2, pfs);
01509 }
01510
01511 Expr bAlpha = multExpr(rat(b), alpha);
01512 Expr aBeta = multExpr(rat(a), beta);
01513 Expr t = minusExpr(bAlpha, aBeta);
01514 Expr d = darkShadow(rat(a*b-1), t);
01515 Expr g = grayShadow(ax, alpha, -a+1, 0);
01516 return newTheorem((d || g) && (!d || !g), A, pf);
01517 }
01518
01519
01520 Theorem ArithTheoremProducer::darkGrayShadow2ba(const Theorem& betaLEbx,
01521 const Theorem& axLEalpha,
01522 const Theorem& isIntAlpha,
01523 const Theorem& isIntBeta,
01524 const Theorem& isIntx) {
01525 const Expr& expr1 = betaLEbx.getExpr();
01526 const Expr& expr2 = axLEalpha.getExpr();
01527 const Expr& isIntAlphaExpr = isIntAlpha.getExpr();
01528 const Expr& isIntBetaExpr = isIntBeta.getExpr();
01529 const Expr& isIntxExpr = isIntx.getExpr();
01530
01531 if(CHECK_PROOFS) {
01532 CHECK_SOUND(isLE(expr1) && isLE(expr2),
01533 "ArithTheoremProducer::darkGrayShadow2ba: Wrong Kind: " +
01534 betaLEbx.toString() + axLEalpha.toString());
01535 }
01536
01537 const Expr& beta = expr1[0];
01538 const Expr& bx = expr1[1];
01539 const Expr& ax = expr2[0];
01540 const Expr& alpha = expr2[1];
01541 Rational a = isMult(ax)? ax[0].getRational() : 1;
01542 Rational b = isMult(bx)? bx[0].getRational() : 1;
01543 const Expr& x = isMult(ax)? ax[1] : ax;
01544
01545 if(CHECK_PROOFS) {
01546
01547 CHECK_SOUND(isIntPred(isIntAlphaExpr) && isIntAlphaExpr[0] == alpha,
01548 "ArithTheoremProducer::darkGrayShadow2ab:\n "
01549 "wrong integrality constraint:\n alpha = "
01550 +alpha.toString()+"\n isIntAlpha = "
01551 +isIntAlphaExpr.toString());
01552 CHECK_SOUND(isIntPred(isIntBetaExpr) && isIntBetaExpr[0] == beta,
01553 "ArithTheoremProducer::darkGrayShadow2ab:\n "
01554 "wrong integrality constraint:\n beta = "
01555 +beta.toString()+"\n isIntBeta = "
01556 +isIntBetaExpr.toString());
01557 CHECK_SOUND(isIntPred(isIntxExpr) && isIntxExpr[0] == x,
01558 "ArithTheoremProducer::darkGrayShadow2ab:\n "
01559 "wrong integrality constraint:\n x = "
01560 +x.toString()+"\n isIntx = "
01561 +isIntxExpr.toString());
01562
01563 CHECK_SOUND(!isMult(ax) || ax.arity() == 2,
01564 "ArithTheoremProducer::darkGrayShadow2ba:\n ax<=alpha: " +
01565 axLEalpha.toString());
01566 CHECK_SOUND(!isMult(bx) || (bx.arity() == 2 && bx[1] == x),
01567 "ArithTheoremProducer::darkGrayShadow2ba:\n beta<=bx: "
01568 +betaLEbx.toString()
01569 +"\n ax<=alpha: "+ axLEalpha.toString());
01570 CHECK_SOUND(1 <= b && b <= a && 2 <= a,
01571 "ArithTheoremProducer::darkGrayShadow2ba:\n beta<=bx: "
01572 +betaLEbx.toString()
01573 +"\n ax<=alpha: "+ axLEalpha.toString());
01574 }
01575 Assumptions A;
01576 if(withAssumptions()) {
01577 vector<Theorem> thms;
01578 thms.push_back(betaLEbx);
01579 thms.push_back(axLEalpha);
01580 thms.push_back(isIntAlpha);
01581 thms.push_back(isIntBeta);
01582 thms.push_back(isIntx);
01583 A = merge(thms);
01584 }
01585 Proof pf;
01586 if(withProof()) {
01587 vector<Proof> pfs;
01588 pfs.push_back(betaLEbx.getProof());
01589 pfs.push_back(axLEalpha.getProof());
01590 pfs.push_back(isIntAlpha.getProof());
01591 pfs.push_back(isIntBeta.getProof());
01592 pfs.push_back(isIntx.getProof());
01593
01594 pf = newPf("dark_grayshadow_2ba", betaLEbx.getExpr(),
01595 axLEalpha.getExpr(), pfs);
01596 }
01597
01598 Expr bAlpha = multExpr(rat(b), alpha);
01599 Expr aBeta = multExpr(rat(a), beta);
01600 Expr t = minusExpr(bAlpha, aBeta);
01601 Expr d = darkShadow(rat(a*b-1), t);
01602 Expr g = grayShadow(bx, beta, 0, b-1);
01603 return newTheorem((d || g) && (!d || !g), A, pf);
01604 }
01605
01606
01607
01608 Theorem ArithTheoremProducer::expandDarkShadow(const Theorem& darkShadow) {
01609 const Expr& theShadow = darkShadow.getExpr();
01610 if(CHECK_PROOFS){
01611 CHECK_SOUND(isDarkShadow(theShadow),
01612 "ArithTheoremProducer::expandDarkShadow: not DARK_SHADOW: " +
01613 theShadow.toString());
01614 }
01615 Assumptions a;
01616 if(withAssumptions())
01617 a = darkShadow.getAssumptionsCopy();
01618 Proof pf;
01619 if(withProof())
01620 pf = newPf("expand_dark_shadow", theShadow, darkShadow.getProof());
01621 return newTheorem(leExpr(theShadow[0], theShadow[1]), a, pf);
01622 }
01623
01624
01625
01626 Theorem ArithTheoremProducer::expandGrayShadow0(const Theorem& grayShadow) {
01627 const Expr& theShadow = grayShadow.getExpr();
01628 if(CHECK_PROOFS) {
01629 CHECK_SOUND(isGrayShadow(theShadow),
01630 "ArithTheoremProducer::expandGrayShadowConst0:"
01631 " not GRAY_SHADOW: " +
01632 theShadow.toString());
01633 CHECK_SOUND(theShadow[2] == theShadow[3],
01634 "ArithTheoremProducer::expandGrayShadow0: c1!=c2: " +
01635 theShadow.toString());
01636 }
01637 Assumptions a;
01638 Proof pf;
01639 if(withAssumptions())
01640 a = grayShadow.getAssumptionsCopy();
01641 if(withProof()) pf = newPf("expand_gray_shadowconst0", theShadow,
01642 grayShadow.getProof());
01643 const Expr& v = theShadow[0];
01644 const Expr& e = theShadow[1];
01645 return newRWTheorem(v, e + theShadow[2], a, pf);
01646 }
01647
01648
01649
01650
01651
01652
01653
01654 Theorem ArithTheoremProducer::splitGrayShadow(const Theorem& gThm) {
01655 const Expr& theShadow = gThm.getExpr();
01656 if(CHECK_PROOFS) {
01657 CHECK_SOUND(isGrayShadow(theShadow),
01658 "ArithTheoremProducer::expandGrayShadowConst: not a shadow" +
01659 theShadow.toString());
01660 }
01661
01662 const Rational& c1 = theShadow[2].getRational();
01663 const Rational& c2 = theShadow[3].getRational();
01664
01665 if(CHECK_PROOFS) {
01666 CHECK_SOUND(c1.isInteger() && c2.isInteger() && c1 < c2,
01667 "ArithTheoremProducer::expandGrayShadow: " +
01668 theShadow.toString());
01669 }
01670
01671 const Expr& v = theShadow[0];
01672 const Expr& e = theShadow[1];
01673
01674 Assumptions a;
01675 Proof pf;
01676 if(withAssumptions())
01677 a = gThm.getAssumptionsCopy();
01678 if(withProof())
01679 pf = newPf("expand_gray_shadow", theShadow, gThm.getProof());
01680 Rational c(floor((c1+c2) / 2));
01681 Expr g1(grayShadow(v, e, c1, c));
01682 Expr g2(grayShadow(v, e, c+1, c2));
01683 return newTheorem((g1 || g2) && (!g1 || !g2), a, pf);
01684 }
01685
01686
01687 Theorem ArithTheoremProducer::expandGrayShadow(const Theorem& gThm) {
01688 const Expr& theShadow = gThm.getExpr();
01689 if(CHECK_PROOFS) {
01690 CHECK_SOUND(isGrayShadow(theShadow),
01691 "ArithTheoremProducer::expandGrayShadowConst: not a shadow" +
01692 theShadow.toString());
01693 }
01694
01695 const Rational& c1 = theShadow[2].getRational();
01696 const Rational& c2 = theShadow[3].getRational();
01697
01698 if(CHECK_PROOFS) {
01699 CHECK_SOUND(c1.isInteger() && c2.isInteger() && c1 < c2,
01700 "ArithTheoremProducer::expandGrayShadow: " +
01701 theShadow.toString());
01702 }
01703
01704 const Expr& v = theShadow[0];
01705 const Expr& e = theShadow[1];
01706
01707 Assumptions a;
01708 Proof pf;
01709 if(withAssumptions())
01710 a = gThm.getAssumptionsCopy();
01711 if(withProof())
01712 pf = newPf("expand_gray_shadow", theShadow, gThm.getProof());
01713 Expr ineq1(leExpr(e+rat(c1), v));
01714 Expr ineq2(leExpr(v, e+rat(c2)));
01715 return newTheorem(ineq1 && ineq2, a, pf);
01716 }
01717
01718
01719
01720 Theorem
01721 ArithTheoremProducer::expandGrayShadowConst(const Theorem& gThm) {
01722 const Expr& theShadow = gThm.getExpr();
01723 const Expr& ax = theShadow[0];
01724 const Expr& cExpr = theShadow[1];
01725 const Expr& bExpr = theShadow[2];
01726
01727 if(CHECK_PROOFS) {
01728 CHECK_SOUND(!isMult(ax) || ax[0].isRational(),
01729 "ArithTheoremProducer::expandGrayShadowConst: "
01730 "'a' in a*x is not a const: " +theShadow.toString());
01731 }
01732
01733 Rational a = isMult(ax)? ax[0].getRational() : 1;
01734
01735 if(CHECK_PROOFS) {
01736 CHECK_SOUND(isGrayShadow(theShadow),
01737 "ArithTheoremProducer::expandGrayShadowConst: "
01738 "not a GRAY_SHADOW: " +theShadow.toString());
01739 CHECK_SOUND(a.isInteger() && a >= 1,
01740 "ArithTheoremProducer::expandGrayShadowConst: "
01741 "'a' is not integer: " +theShadow.toString());
01742 CHECK_SOUND(cExpr.isRational(),
01743 "ArithTheoremProducer::expandGrayShadowConst: "
01744 "'c' is not rational" +theShadow.toString());
01745 CHECK_SOUND(bExpr.isRational() && bExpr.getRational().isInteger(),
01746 "ArithTheoremProducer::expandGrayShadowConst: b not integer: "
01747 +theShadow.toString());
01748 }
01749
01750 const Rational& b = bExpr.getRational();
01751 const Rational& c = cExpr.getRational();
01752 Rational j = constRHSGrayShadow(c,b,a);
01753
01754 Rational signB = (b>0)? 1 : -1;
01755
01756 Rational bAbs = abs(b);
01757
01758 Assumptions assump;
01759 Proof pf;
01760 Theorem conc;
01761
01762 if(withAssumptions())
01763 assump = gThm.getAssumptionsCopy();
01764
01765 if(bAbs < j) {
01766 if(withProof())
01767 pf = newPf("expand_gray_shadow_const_0", theShadow,
01768 gThm.getProof());
01769 conc = newTheorem(d_em->falseExpr(), assump, pf);
01770 } else if(bAbs < a+j) {
01771 if(withProof())
01772 pf = newPf("expand_gray_shadow_const_1", theShadow,
01773 gThm.getProof());
01774 conc = newRWTheorem(ax, rat(c+b-signB*j), assump, pf);
01775 } else {
01776 if(withProof())
01777 pf = newPf("expand_gray_shadow_const", theShadow,
01778 gThm.getProof());
01779 Expr newGrayShadow(Expr(GRAY_SHADOW, ax, cExpr, rat(b-signB*(a+j))));
01780 conc = newTheorem(ax.eqExpr(rat(c+b-signB*j)).orExpr(newGrayShadow),
01781 assump, pf);
01782 }
01783
01784 return conc;
01785 }
01786
01787
01788 Theorem
01789 ArithTheoremProducer::grayShadowConst(const Theorem& gThm) {
01790 const Expr& g = gThm.getExpr();
01791 bool checkProofs(CHECK_PROOFS);
01792 if(checkProofs) {
01793 CHECK_SOUND(isGrayShadow(g), "ArithTheoremProducer::grayShadowConst("
01794 +g.toString()+")");
01795 }
01796
01797 const Expr& ax = g[0];
01798 const Expr& e = g[1];
01799 const Rational& c1 = g[2].getRational();
01800 const Rational& c2 = g[3].getRational();
01801 Expr aExpr, x;
01802 d_theoryArith->separateMonomial(ax, aExpr, x);
01803
01804 if(checkProofs) {
01805 CHECK_SOUND(e.isRational() && e.getRational().isInteger(),
01806 "ArithTheoremProducer::grayShadowConst("+g.toString()+")");
01807 CHECK_SOUND(aExpr.isRational(),
01808 "ArithTheoremProducer::grayShadowConst("+g.toString()+")");
01809 }
01810
01811 const Rational& a = aExpr.getRational();
01812 const Rational& c = e.getRational();
01813
01814 if(checkProofs) {
01815 CHECK_SOUND(a.isInteger() && a >= 2,
01816 "ArithTheoremProducer::grayShadowConst("+g.toString()+")");
01817 }
01818
01819 Rational newC1 = ceil((c1+c)/a), newC2 = floor((c2+c)/a);
01820 Expr newG((newC1 > newC2)? d_em->falseExpr()
01821 : grayShadow(x, rat(0), newC1, newC2));
01822 Assumptions assump;
01823 Proof pf;
01824 if(withAssumptions()) assump = gThm.getAssumptionsCopy();
01825 if(withProof())
01826 pf = newPf("gray_shadow_const", g, gThm.getProof());
01827 return newTheorem(newG, assump, pf);
01828 }
01829
01830
01831 Rational ArithTheoremProducer::constRHSGrayShadow(const Rational& c,
01832 const Rational& b,
01833 const Rational& a) {
01834 DebugAssert(c.isInteger() &&
01835 b.isInteger() &&
01836 a.isInteger() &&
01837 b != 0,
01838 "ArithTheoremProducer::constRHSGrayShadow: a, b, c must be ints");
01839 if (b > 0)
01840 return mod(c+b, a);
01841 else
01842 return mod(a-(c+b), a);
01843 }
01844
01845
01846
01847
01848
01849 Theorem ArithTheoremProducer::lessThanToLE(const Theorem& less,
01850 const Theorem& isIntLHS,
01851 const Theorem& isIntRHS,
01852 bool changeRight) {
01853 const Expr& ineq = less.getExpr();
01854 const Expr& isIntLHSexpr = isIntLHS.getExpr();
01855 const Expr& isIntRHSexpr = isIntRHS.getExpr();
01856
01857 if(CHECK_PROOFS) {
01858 CHECK_SOUND(isLT(ineq),
01859 "ArithTheoremProducer::LTtoLE: ineq must be <");
01860
01861 CHECK_SOUND(isIntPred(isIntLHSexpr) && isIntLHSexpr[0] == ineq[0],
01862 "ArithTheoremProducer::lessThanToLE: bad integrality check:\n"
01863 " ineq = "+ineq.toString()+"\n isIntLHS = "
01864 +isIntLHSexpr.toString());
01865 CHECK_SOUND(isIntPred(isIntRHSexpr) && isIntRHSexpr[0] == ineq[1],
01866 "ArithTheoremProducer::lessThanToLE: bad integrality check:\n"
01867 " ineq = "+ineq.toString()+"\n isIntRHS = "
01868 +isIntRHSexpr.toString());
01869 }
01870 Assumptions a;
01871 Proof pf;
01872 if(withAssumptions()) {
01873 vector<Theorem> thms;
01874 thms.push_back(less);
01875 thms.push_back(isIntLHS);
01876 thms.push_back(isIntRHS);
01877 a = merge(thms);
01878 }
01879 if(withProof()) {
01880 vector<Proof> pfs;
01881 pfs.push_back(less.getProof());
01882 pfs.push_back(isIntLHS.getProof());
01883 pfs.push_back(isIntRHS.getProof());
01884 pf = newPf(changeRight? "lessThan_To_LE_rhs" : "lessThan_To_LE_lhs",
01885 ineq, pfs);
01886 }
01887 Expr le = changeRight?
01888 leExpr(ineq[0], ineq[1] + rat(-1))
01889 : leExpr(ineq[0] + rat(1), ineq[1]);
01890 return newRWTheorem(ineq, le, a, pf);
01891 }
01892
01893
01894
01895
01896
01897
01898
01899
01900
01901
01902 Theorem
01903 ArithTheoremProducer::intVarEqnConst(const Expr& eqn,
01904 const Theorem& isIntx) {
01905 const Expr& left(eqn[0]);
01906 const Expr& right(eqn[1]);
01907 const Expr& isIntxexpr(isIntx.getExpr());
01908
01909 if(CHECK_PROOFS) {
01910 CHECK_SOUND((isMult(right) && right[0].isRational())
01911 || (right.arity() == 2 && isPlus(right)
01912 && right[0].isRational()
01913 && ((!isMult(right[1]) || right[1][0].isRational()))),
01914 "ArithTheoremProducer::intVarEqnConst: "
01915 "rhs has a wrong format: " + right.toString());
01916 CHECK_SOUND(left.isRational() && 0 == left.getRational(),
01917 "ArithTheoremProducer:intVarEqnConst:left is not a zero: " +
01918 left.toString());
01919 }
01920
01921 Expr x(right);
01922 Rational a(1), c(0);
01923 if(isMult(right)) {
01924 Expr aExpr;
01925 d_theoryArith->separateMonomial(right, aExpr, x);
01926 a = aExpr.getRational();
01927 } else {
01928 c = right[0].getRational();
01929 Expr aExpr;
01930 d_theoryArith->separateMonomial(right[1], aExpr, x);
01931 a = aExpr.getRational();
01932 }
01933 if(CHECK_PROOFS) {
01934 CHECK_SOUND(isIntPred(isIntxexpr) && isIntxexpr[0] == x,
01935 "ArithTheoremProducer:intVarEqnConst: "
01936 "bad integrality constraint:\n right = " +
01937 right.toString()+"\n isIntx = "+isIntxexpr.toString());
01938 CHECK_SOUND(a!=0, "ArithTheoremProducer:intVarEqnConst: eqn = "
01939 +eqn.toString());
01940 }
01941 Assumptions assump;
01942 if(withAssumptions())
01943 assump = isIntx.getAssumptionsCopy();
01944 Proof pf;
01945 if(withProof())
01946 pf = newPf("int_const_eq", eqn, isIntx.getProof());
01947
01948
01949 Rational r(-c/a);
01950
01951 if(r.isInteger())
01952 return newRWTheorem(eqn, x.eqExpr(rat(r)), assump, pf);
01953 else
01954 return newRWTheorem(eqn, d_em->falseExpr(), assump, pf);
01955 }
01956
01957
01958 Expr
01959 ArithTheoremProducer::create_t(const Expr& eqn) {
01960 const Expr& lhs = eqn[0];
01961 DebugAssert(isMult(lhs),
01962 CLASS_NAME "create_t : lhs must be a MULT"
01963 + lhs.toString());
01964 const Expr& x = lhs[1];
01965 Rational m = lhs[0].getRational()+1;
01966 DebugAssert(m > 0, "ArithTheoremProducer::create_t: m = "+m.toString());
01967 vector<Expr> kids;
01968 if(isPlus(eqn[1]))
01969 sumModM(kids, eqn[1], m, m);
01970 else
01971 kids.push_back(monomialModM(eqn[1], m, m));
01972
01973 kids.push_back(multExpr(rat(1/m), x));
01974 return plusExpr(kids);
01975 }
01976
01977 Expr
01978 ArithTheoremProducer::create_t2(const Expr& lhs, const Expr& rhs,
01979 const Expr& sigma) {
01980 Rational m = lhs[0].getRational()+1;
01981 DebugAssert(m > 0, "ArithTheoremProducer::create_t2: m = "+m.toString());
01982 vector<Expr> kids;
01983 if(isPlus(rhs))
01984 sumModM(kids, rhs, m, -1);
01985 else {
01986 kids.push_back(rat(0));
01987 Expr monom = monomialModM(rhs, m, -1);
01988 if(!monom.isRational())
01989 kids.push_back(monom);
01990 else
01991 DebugAssert(monom.getRational() == 0, "");
01992 }
01993 kids.push_back(rat(m)*sigma);
01994 return plusExpr(kids);
01995 }
01996
01997 Expr
01998 ArithTheoremProducer::create_t3(const Expr& lhs, const Expr& rhs,
01999 const Expr& sigma) {
02000 const Rational& a = lhs[0].getRational();
02001 Rational m = a+1;
02002 DebugAssert(m > 0, "ArithTheoremProducer::create_t3: m = "+m.toString());
02003 vector<Expr> kids;
02004 if(isPlus(rhs))
02005 sumMulF(kids, rhs, m, 1);
02006 else {
02007 kids.push_back(rat(0));
02008 Expr monom = monomialMulF(rhs, m, 1);
02009 if(!monom.isRational())
02010 kids.push_back(monom);
02011 else
02012 DebugAssert(monom.getRational() == 0, "");
02013 }
02014 kids.push_back(rat(-a)*sigma);
02015 return plusExpr(kids);
02016 }
02017
02018 Rational
02019 ArithTheoremProducer::modEq(const Rational& i, const Rational& m) {
02020 DebugAssert(m > 0, "ArithTheoremProducer::modEq: m = "+m.toString());
02021 Rational half(1,2);
02022 Rational res((i - m*(floor((i/m) + half))));
02023 TRACE("arith eq", "modEq("+i.toString()+", "+m.toString()+") = ", res, "");
02024 return res;
02025 }
02026
02027 Rational
02028 ArithTheoremProducer::f(const Rational& i, const Rational& m) {
02029 DebugAssert(m > 0, "ArithTheoremProducer::f: m = "+m.toString());
02030 Rational half(1,2);
02031 return (floor(i/m + half)+modEq(i,m));
02032 }
02033
02034 void
02035 ArithTheoremProducer::sumModM(vector<Expr>& summands, const Expr& sum,
02036 const Rational& m, const Rational& divisor) {
02037 DebugAssert(divisor != 0, "ArithTheoremProducer::sumModM: divisor = "
02038 +divisor.toString());
02039 Expr::iterator i = sum.begin();
02040 DebugAssert(i != sum.end(), CLASS_NAME "::sumModM");
02041 Rational C = i->getRational();
02042 C = modEq(C,m)/divisor;
02043 summands.push_back(rat(C));
02044 i++;
02045 for(Expr::iterator iend=sum.end(); i!=iend; ++i) {
02046 Expr monom = monomialModM(*i, m, divisor);
02047 if(!monom.isRational())
02048 summands.push_back(monom);
02049 else
02050 DebugAssert(monom.getRational() == 0, "");
02051 }
02052 }
02053
02054 Expr
02055 ArithTheoremProducer::monomialModM(const Expr& i,
02056 const Rational& m, const Rational& divisor)
02057 {
02058 DebugAssert(divisor != 0, "ArithTheoremProducer::monomialModM: divisor = "
02059 +divisor.toString());
02060 Expr res;
02061 if(isMult(i)) {
02062 Rational ai = i[0].getRational();
02063 ai = modEq(ai,m)/divisor;
02064 if(0 == ai) res = rat(0);
02065 else if(1 == ai && i.arity() == 2) res = i[1];
02066 else {
02067 vector<Expr> kids = i.getKids();
02068 kids[0] = rat(ai);
02069 res = multExpr(kids);
02070 }
02071 } else {
02072 Rational ai = modEq(1,m)/divisor;
02073 if(1 == ai) res = i;
02074 else res = rat(ai)*i;
02075 }
02076 DebugAssert(!res.isNull(), "ArithTheoremProducer::monomialModM()");
02077 TRACE("arith eq", "monomialModM(i="+i.toString()+", m="+m.toString()
02078 +", div="+divisor.toString()+") = ", res, "");
02079 return res;
02080 }
02081
02082 void
02083 ArithTheoremProducer::sumMulF(vector<Expr>& summands, const Expr& sum,
02084 const Rational& m, const Rational& divisor) {
02085 DebugAssert(divisor != 0, "ArithTheoremProducer::sumMulF: divisor = "
02086 +divisor.toString());
02087 Expr::iterator i = sum.begin();
02088 DebugAssert(i != sum.end(), CLASS_NAME "::sumModM");
02089 Rational C = i->getRational();
02090 C = f(C,m)/divisor;
02091 summands.push_back(rat(C));
02092 i++;
02093 for(Expr::iterator iend=sum.end(); i!=iend; ++i) {
02094 Expr monom = monomialMulF(*i, m, divisor);
02095 if(!monom.isRational())
02096 summands.push_back(monom);
02097 else
02098 DebugAssert(monom.getRational() == 0, "");
02099 }
02100 }
02101
02102 Expr
02103 ArithTheoremProducer::monomialMulF(const Expr& i,
02104 const Rational& m, const Rational& divisor)
02105 {
02106 DebugAssert(divisor != 0, "ArithTheoremProducer::monomialMulF: divisor = "
02107 +divisor.toString());
02108 Rational ai = isMult(i) ? (i)[0].getRational() : 1;
02109 Expr xi = isMult(i) ? (i)[1] : (i);
02110 ai = f(ai,m)/divisor;
02111 if(0 == ai) return rat(0);
02112 if(1 == ai) return xi;
02113 return multExpr(rat(ai), xi);
02114 }
02115
02116
02117
02118
02119 Expr
02120 ArithTheoremProducer::substitute(const Expr& term, ExprMap<Expr>& eMap)
02121 {
02122 ExprMap<Expr>::iterator i, iend = eMap.end();
02123
02124 i = eMap.find(term);
02125 if(iend != i)
02126 return (*i).second;
02127
02128 if (isMult(term)) {
02129
02130 i = eMap.find(term[1]);
02131 if(iend != i)
02132 return term[0]*(*i).second;
02133 else
02134 return term;
02135 }
02136
02137 if(isPlus(term)) {
02138 vector<Expr> output;
02139 for(Expr::iterator j = term.begin(), jend = term.end(); j != jend; ++j)
02140 output.push_back(substitute(*j, eMap));
02141 return plusExpr(output);
02142 }
02143 return term;
02144 }
02145
02146 bool ArithTheoremProducer::greaterthan(const Expr & l, const Expr & r)
02147 {
02148
02149 if (l==r) return false;
02150
02151 switch(l.getKind()) {
02152 case RATIONAL_EXPR:
02153 DebugAssert(!r.isRational(), "");
02154 return true;
02155 break;
02156 case POW:
02157 switch (r.getKind()) {
02158 case RATIONAL_EXPR:
02159
02160
02161 return false;
02162 break;
02163 case POW:
02164
02165
02166 return
02167 ((r[1] < l[1]) ||
02168 ((r[1]==l[1]) && (r[0].getRational() < l[0].getRational())));
02169 break;
02170
02171 case MULT:
02172 DebugAssert(r.arity() > 1, "");
02173 DebugAssert((r.arity() > 2) || (r[1] != l), "");
02174 if (r[1] == l) return false;
02175 return greaterthan(l, r[1]);
02176 break;
02177 case PLUS:
02178 DebugAssert(false, "");
02179 return true;
02180 break;
02181 default:
02182
02183 return ((r < l[1]) || ((r == l[1]) && l[0].getRational() > 1));
02184 break;
02185 }
02186 break;
02187 case MULT:
02188 DebugAssert(l.arity() > 1, "");
02189 switch (r.getKind()) {
02190 case RATIONAL_EXPR:
02191 return false;
02192 break;
02193 case POW:
02194 DebugAssert(l.arity() > 1, "");
02195 DebugAssert((l.arity() > 2) || (l[1] != r), "");
02196
02197
02198 return ((l[1] == r) || greaterthan(l[1], r));
02199 break;
02200 case MULT:
02201 {
02202
02203 DebugAssert(r.arity() > 1, "");
02204 Expr::iterator i = l.begin();
02205 Expr::iterator j = r.begin();
02206 ++i;
02207 ++j;
02208 for (; i != l.end() && j != r.end(); ++i, ++j) {
02209 if (*i == *j)
02210 continue;
02211 return greaterthan(*i,*j);
02212 }
02213 DebugAssert(i != l.end() || j != r.end(), "");
02214 if (i == l.end()) {
02215
02216 return false;
02217 }
02218 else
02219 {
02220
02221 return true;
02222 }
02223 }
02224 break;
02225 case PLUS:
02226 DebugAssert(false, "");
02227 return true;
02228 break;
02229 default:
02230
02231 DebugAssert((l.arity() > 2) || (l[1] != r), "");
02232 return ((l[1] == r) || greaterthan(l[1], r));
02233 break;
02234 }
02235 break;
02236 case PLUS:
02237 DebugAssert(false, "");
02238 return true;
02239 break;
02240 default:
02241
02242 switch (r.getKind()) {
02243 case RATIONAL_EXPR:
02244 return false;
02245 break;
02246 case POW:
02247 return ((r[1] < l) || ((r[1] == l) && (r[0].getRational() < 1)));
02248 break;
02249 case MULT:
02250 DebugAssert(r.arity() > 1, "");
02251 DebugAssert((r.arity() > 2) || (r[1] != l), "");
02252 if (l == r[1]) return false;
02253 return greaterthan(l,r[1]);
02254 break;
02255 case PLUS:
02256 DebugAssert(false, "");
02257 return true;
02258 break;
02259 default:
02260
02261 return (r < l);
02262 break;
02263 }
02264 break;
02265 }
02266 }
02267
02268
02269 Theorem
02270 ArithTheoremProducer::eqElimIntRule(const Theorem& eqn, const Theorem& isIntx,
02271 const vector<Theorem>& isIntVars) {
02272 TRACE("arith eq", "eqElimIntRule(", eqn.getExpr(), ") {");
02273 Assumptions assump;
02274 Proof pf;
02275
02276 if(CHECK_PROOFS)
02277 CHECK_SOUND(eqn.isRewrite(),
02278 "ArithTheoremProducer::eqElimInt: input must be an equation" +
02279 eqn.toString());
02280
02281 const Expr& lhs = eqn.getLHS();
02282 const Expr& rhs = eqn.getRHS();
02283 Expr a, x;
02284 d_theoryArith->separateMonomial(lhs, a, x);
02285
02286 if(CHECK_PROOFS) {
02287
02288 const Expr& isIntxe = isIntx.getExpr();
02289 CHECK_SOUND(isIntPred(isIntxe) && isIntxe[0] == x,
02290 "ArithTheoremProducer::eqElimInt\n eqn = "
02291 +eqn.getExpr().toString()
02292 +"\n isIntx = "+isIntxe.toString());
02293 CHECK_SOUND(isRational(a) && a.getRational().isInteger()
02294 && a.getRational() >= 2,
02295 "ArithTheoremProducer::eqElimInt:\n lhs = "+lhs.toString());
02296
02297
02298 CHECK_SOUND(!isDivide(rhs),
02299 "ArithTheoremProducer::eqElimInt:\n rhs = "+rhs.toString());
02300
02301 if(!isPlus(rhs)) {
02302 Expr c, v;
02303 d_theoryArith->separateMonomial(rhs, c, v);
02304 CHECK_SOUND(isIntVars.size() == 1
02305 && isIntPred(isIntVars[0].getExpr())
02306 && isIntVars[0].getExpr()[0] == v
02307 && isRational(c) && c.getRational().isInteger(),
02308 "ArithTheoremProducer::eqElimInt:\n rhs = "+rhs.toString()
02309 +"isIntVars.size = "+int2string(isIntVars.size()));
02310 } else {
02311 CHECK_SOUND(isIntVars.size() + 1 == (size_t)rhs.arity(),
02312 "ArithTheoremProducer::eqElimInt: rhs = "+rhs.toString());
02313
02314 CHECK_SOUND(isRational(rhs[0]) && rhs[0].getRational().isInteger(),
02315 "ArithTheoremProducer::eqElimInt: rhs = "+rhs.toString());
02316
02317 for(size_t i=0, iend=isIntVars.size(); i<iend; ++i) {
02318 Expr c, v;
02319 d_theoryArith->separateMonomial(rhs[i+1], c, v);
02320 const Expr& isInt(isIntVars[i].getExpr());
02321 CHECK_SOUND(isIntPred(isInt) && isInt[0] == v
02322 && isRational(c) && c.getRational().isInteger(),
02323 "ArithTheoremProducer::eqElimInt:\n rhs["+int2string(i+1)
02324 +"] = "+rhs[i+1].toString()
02325 +"\n isInt = "+isInt.toString());
02326 }
02327 }
02328 }
02329
02330
02331 static int varCount(0);
02332 Expr newVar = d_em->newBoundVarExpr("_int_var", int2string(varCount++));
02333 newVar.setType(intType());
02334 Expr t2 = create_t2(lhs, rhs, newVar);
02335 Expr t3 = create_t3(lhs, rhs, newVar);
02336 vector<Expr> vars;
02337 vars.push_back(newVar);
02338 Expr res = d_em->newClosureExpr(EXISTS, vars,
02339 x.eqExpr(t2) && rat(0).eqExpr(t3));
02340
02341 if(withAssumptions()) {
02342 vector<Theorem> thms(isIntVars);
02343 thms.push_back(isIntx);
02344 thms.push_back(eqn);
02345 assump = merge(thms);
02346 }
02347
02348 if(withProof()) {
02349 vector<Proof> pfs;
02350 pfs.push_back(eqn.getProof());
02351 pfs.push_back(isIntx.getProof());
02352 vector<Theorem>::const_iterator i=isIntVars.begin(), iend=isIntVars.end();
02353 for(; i!=iend; ++i)
02354 pfs.push_back(i->getProof());
02355 pf = newPf("eq_elim_int", eqn.getExpr(), pfs);
02356 }
02357
02358 Theorem thm(newTheorem(res, assump, pf));
02359 TRACE("arith eq", "eqElimIntRule => ", thm.getExpr(), " }");
02360 return thm;
02361 }
02362
02363
02364 Theorem
02365 ArithTheoremProducer::isIntConst(const Expr& e) {
02366 Assumptions a;
02367 Proof pf;
02368
02369 if(CHECK_PROOFS) {
02370 CHECK_SOUND(isIntPred(e) && e[0].isRational(),
02371 "ArithTheoremProducer::isIntConst(e = "
02372 +e.toString()+")");
02373 }
02374 if(withProof())
02375 pf = newPf("is_int_const", e);
02376 bool isInt = e[0].getRational().isInteger();
02377 return newRWTheorem(e, isInt? d_em->trueExpr() : d_em->falseExpr(), a, pf);
02378 }
02379
02380
02381 Theorem
02382 ArithTheoremProducer::equalLeaves1(const Theorem& thm)
02383 {
02384 Assumptions a;
02385 Proof pf;
02386 const Expr& e = thm.getRHS();
02387
02388 if (CHECK_PROOFS) {
02389 CHECK_SOUND(e[1].getKind() == RATIONAL_EXPR &&
02390 e[1].getRational() == Rational(0) &&
02391 e[0].getKind() == PLUS &&
02392 e[0].arity() == 3 &&
02393 e[0][0].getKind() == RATIONAL_EXPR &&
02394 e[0][0].getRational() == Rational(0) &&
02395 e[0][1].getKind() == MULT &&
02396 e[0][1].arity() == 2 &&
02397 e[0][1][0].getKind() == RATIONAL_EXPR &&
02398 e[0][1][0].getRational() == Rational(-1),
02399 "equalLeaves1");
02400 }
02401 if (withAssumptions())
02402 a = thm.getAssumptions();
02403 if (withProof())
02404 {
02405 vector<Proof> pfs;
02406 pfs.push_back(thm.getProof());
02407 pf = newPf("equalLeaves1", e, pfs);
02408 }
02409 return newRWTheorem(e, e[0][1][1].eqExpr(e[0][2]), a, pf);
02410 }
02411
02412
02413 Theorem
02414 ArithTheoremProducer::equalLeaves2(const Theorem& thm)
02415 {
02416 Assumptions a;
02417 Proof pf;
02418 const Expr& e = thm.getRHS();
02419
02420 if (CHECK_PROOFS) {
02421 CHECK_SOUND(e[0].getKind() == RATIONAL_EXPR &&
02422 e[0].getRational() == Rational(0) &&
02423 e[1].getKind() == PLUS &&
02424 e[1].arity() == 3 &&
02425 e[1][0].getKind() == RATIONAL_EXPR &&
02426 e[1][0].getRational() == Rational(0) &&
02427 e[1][1].getKind() == MULT &&
02428 e[1][1].arity() == 2 &&
02429 e[1][1][0].getKind() == RATIONAL_EXPR &&
02430 e[1][1][0].getRational() == Rational(-1),
02431 "equalLeaves2");
02432 }
02433 if (withAssumptions())
02434 a = thm.getAssumptions();
02435 if (withProof())
02436 {
02437 vector<Proof> pfs;
02438 pfs.push_back(thm.getProof());
02439 pf = newPf("equalLeaves2", e, pfs);
02440 }
02441 return newRWTheorem(e, e[1][1][1].eqExpr(e[1][2]), a, pf);
02442 }
02443
02444
02445 Theorem
02446 ArithTheoremProducer::equalLeaves3(const Theorem& thm)
02447 {
02448 Assumptions a;
02449 Proof pf;
02450 const Expr& e = thm.getRHS();
02451
02452 if (CHECK_PROOFS) {
02453 CHECK_SOUND(e[1].getKind() == RATIONAL_EXPR &&
02454 e[1].getRational() == Rational(0) &&
02455 e[0].getKind() == PLUS &&
02456 e[0].arity() == 3 &&
02457 e[0][0].getKind() == RATIONAL_EXPR &&
02458 e[0][0].getRational() == Rational(0) &&
02459 e[0][2].getKind() == MULT &&
02460 e[0][2].arity() == 2 &&
02461 e[0][2][0].getKind() == RATIONAL_EXPR &&
02462 e[0][2][0].getRational() == Rational(-1),
02463 "equalLeaves3");
02464 }
02465 if (withAssumptions())
02466 a = thm.getAssumptions();
02467 if (withProof())
02468 {
02469 vector<Proof> pfs;
02470 pfs.push_back(thm.getProof());
02471 pf = newPf("equalLeaves3", e, pfs);
02472 }
02473 return newRWTheorem(e, e[0][2][1].eqExpr(e[0][1]), a, pf);
02474 }
02475
02476
02477 Theorem
02478 ArithTheoremProducer::equalLeaves4(const Theorem& thm)
02479 {
02480 Assumptions a;
02481 Proof pf;
02482 const Expr& e = thm.getRHS();
02483
02484 if (CHECK_PROOFS) {
02485 CHECK_SOUND(e[0].getKind() == RATIONAL_EXPR &&
02486 e[0].getRational() == Rational(0) &&
02487 e[1].getKind() == PLUS &&
02488 e[1].arity() == 3 &&
02489 e[1][0].getKind() == RATIONAL_EXPR &&
02490 e[1][0].getRational() == Rational(0) &&
02491 e[1][2].getKind() == MULT &&
02492 e[1][2].arity() == 2 &&
02493 e[1][2][0].getKind() == RATIONAL_EXPR &&
02494 e[1][2][0].getRational() == Rational(-1),
02495 "equalLeaves4");
02496 }
02497 if (withAssumptions())
02498 a = thm.getAssumptions();
02499 if (withProof())
02500 {
02501 vector<Proof> pfs;
02502 pfs.push_back(thm.getProof());
02503 pf = newPf("equalLeaves4", e, pfs);
02504 }
02505 return newRWTheorem(e, e[1][2][1].eqExpr(e[1][1]), a, pf);
02506 }
02507
02508 Theorem
02509 ArithTheoremProducer::diseqToIneq(const Theorem& diseq) {
02510 Assumptions a;
02511 Proof pf;
02512
02513 const Expr& e = diseq.getExpr();
02514
02515 if(CHECK_PROOFS) {
02516 CHECK_SOUND(e.isNot() && e[0].isEq(),
02517 "ArithTheoremProducer::diseqToIneq: expected disequality:\n"
02518 " e = "+e.toString());
02519 }
02520
02521 const Expr& x = e[0][0];
02522 const Expr& y = e[0][1];
02523
02524 if(withAssumptions())
02525 a = diseq.getAssumptions();
02526 if(withProof())
02527 pf = newPf(e, diseq.getProof());
02528 return newTheorem(ltExpr(x,y).orExpr(gtExpr(x,y)), a, pf);
02529 }