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