00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030 #define _CVC3_TRUSTED_
00031
00032 #include "arith_theorem_producer.h"
00033 #include "theory_core.h"
00034 #include "theory_arith_new.h"
00035
00036 using namespace std;
00037 using namespace CVC3;
00038
00039
00040
00041
00042
00043 ArithProofRules* TheoryArithNew::createProofRules() {
00044 return new ArithTheoremProducer(theoryCore()->getTM(), this);
00045 }
00046
00047
00048
00049
00050
00051
00052 #define CLASS_NAME "ArithTheoremProducer"
00053
00054
00055 Theorem ArithTheoremProducer::varToMult(const Expr& e) {
00056 Proof pf;
00057 if(withProof()) pf = newPf("var_to_mult", e);
00058 return newRWTheorem(e, (rat(1) * e), Assumptions::emptyAssump(), pf);
00059 }
00060
00061
00062 Theorem ArithTheoremProducer::uMinusToMult(const Expr& e) {
00063
00064 Proof pf;
00065
00066
00067 if(withProof()) pf = newPf("uminus_to_mult", e);
00068
00069
00070 return newRWTheorem((-e), (rat(-1) * e), Assumptions::emptyAssump(), pf);
00071 }
00072
00073
00074
00075 Theorem ArithTheoremProducer::minusToPlus(const Expr& x, const Expr& y) {
00076
00077 Proof pf;
00078
00079
00080 if (withProof()) pf = newPf("minus_to_plus", x, y);
00081
00082
00083 return newRWTheorem((x-y), (x + (rat(-1) * y)), Assumptions::emptyAssump(), pf);
00084 }
00085
00086
00087
00088
00089 Theorem ArithTheoremProducer::canonUMinusToDivide(const Expr& e) {
00090 Proof pf;
00091 if(withProof()) pf = newPf("canon_uminus", e);
00092 return newRWTheorem((-e), (e / rat(-1)), Assumptions::emptyAssump(), pf);
00093 }
00094
00095
00096
00097
00098 Theorem ArithTheoremProducer::canonDivideConst(const Expr& c,
00099 const Expr& d) {
00100
00101 if(CHECK_PROOFS) {
00102 CHECK_SOUND(isRational(c),
00103 CLASS_NAME "::canonDivideConst:\n c not a constant: "
00104 + c.toString());
00105 CHECK_SOUND(isRational(d),
00106 CLASS_NAME "::canonDivideConst:\n d not a constant: "
00107 + d.toString());
00108 }
00109 Proof pf;
00110 if(withProof())
00111 pf = newPf("canon_divide_const", c, d, d_hole);
00112 const Rational& dr = d.getRational();
00113 return newRWTheorem((c/d), (rat(dr==0? 0 : (c.getRational()/dr))), Assumptions::emptyAssump(), pf);
00114 }
00115
00116
00117 Theorem ArithTheoremProducer::canonDivideMult(const Expr& cx,
00118 const Expr& d) {
00119
00120 if(CHECK_PROOFS) {
00121 CHECK_SOUND(isMult(cx) && isRational(cx[0]),
00122 CLASS_NAME "::canonDivideMult:\n "
00123 "Not a (c * x) expression: "
00124 + cx.toString());
00125 CHECK_SOUND(isRational(d),
00126 CLASS_NAME "::canonDivideMult:\n "
00127 "d is not a constant: " + d.toString());
00128 }
00129 const Rational& dr = d.getRational();
00130 Rational cdr(dr==0? 0 : (cx[0].getRational()/dr));
00131 Expr cd(rat(cdr));
00132 Proof pf;
00133 if(withProof())
00134 pf = newPf("canon_divide_mult", cx[0], cx[1], d);
00135
00136 if(cdr == 1)
00137 return newRWTheorem((cx/d), (cx[1]), Assumptions::emptyAssump(), pf);
00138 else if(cdr == 0)
00139 return newRWTheorem((cx/d), cd, Assumptions::emptyAssump(), pf);
00140 else
00141 return newRWTheorem((cx/d), (cd*cx[1]), Assumptions::emptyAssump(), pf);
00142 }
00143
00144
00145 Theorem ArithTheoremProducer::canonDividePlus(const Expr& sum, const Expr& d) {
00146 if(CHECK_PROOFS) {
00147 CHECK_SOUND(isPlus(sum) && sum.arity() >= 2 && isRational(sum[0]),
00148 CLASS_NAME "::canonUMinusPlus:\n "
00149 "Expr is not a canonical sum: "
00150 + sum.toString());
00151 CHECK_SOUND(isRational(d),
00152 CLASS_NAME "::canonUMinusPlus:\n "
00153 "d is not a const: " + d.toString());
00154 }
00155
00156 Proof pf;
00157 if(withProof())
00158 pf = newPf("canon_divide_plus", rat(sum.arity()),
00159 sum.begin(), sum.end());
00160 vector<Expr> newKids;
00161 for(Expr::iterator i=sum.begin(), iend=sum.end(); i!=iend; ++i)
00162 newKids.push_back((*i)/d);
00163
00164 return newRWTheorem((sum/d), (plusExpr(newKids)), Assumptions::emptyAssump(), pf);
00165 }
00166
00167
00168 Theorem ArithTheoremProducer::canonDivideVar(const Expr& e, const Expr& d) {
00169 if(CHECK_PROOFS) {
00170 CHECK_SOUND(isRational(d),
00171 CLASS_NAME "::canonDivideVar:\n "
00172 "d is not a const: " + d.toString());
00173 }
00174 Proof pf;
00175
00176 if(withProof())
00177 pf = newPf("canon_divide_var", e);
00178
00179 const Rational& dr = d.getRational();
00180 if(dr == 1)
00181 return newRWTheorem(e/d, e, Assumptions::emptyAssump(), pf);
00182 if(dr == 0)
00183 return newRWTheorem(e/d, d, Assumptions::emptyAssump(), pf);
00184 else
00185 return newRWTheorem(e/d, rat(1/dr) * e, Assumptions::emptyAssump(), pf);
00186 }
00187
00188
00189
00190
00191
00192
00193
00194
00195
00196
00197
00198
00199
00200
00201
00202
00203 Expr ArithTheoremProducer::simplifiedMultExpr(std::vector<Expr> & mulKids) {
00204
00205
00206 DebugAssert(mulKids.size() >= 1 && mulKids[0].isRational(), "");
00207
00208
00209 if (mulKids.size() == 1) return mulKids[0];
00210
00211 else return multExpr(mulKids);
00212 }
00213
00214 Expr ArithTheoremProducer::canonMultConstMult(const Expr & c, const Expr & e) {
00215
00216
00217 DebugAssert(c.isRational() && e.getKind() == MULT, "ArithTheoremProducer::canonMultConstMult: c must be a rational a e must be a MULT");
00218
00219
00220 DebugAssert ((e.arity() > 1) && (e[0].isRational()), "arith_theorem_producer::canonMultConstMult: a canonized MULT expression must have \
00221 arity greater than 1: and first child must be rational " + e.toString());
00222
00223
00224 std::vector<Expr> mulKids;
00225
00226
00227 Expr::iterator i = e.begin();
00228 mulKids.push_back(rat(c.getRational() * (*i).getRational()));
00229
00230 for(i ++; i != e.end(); i ++)
00231 mulKids.push_back(*i);
00232
00233
00234 return simplifiedMultExpr(mulKids);
00235 }
00236
00237 Expr ArithTheoremProducer::canonMultConstPlus(const Expr & e1, const Expr & e2) {
00238
00239
00240 DebugAssert(e1.isRational() && e2.getKind() == PLUS && e2.arity() > 0, "");
00241
00242
00243 std::vector<Theorem> thmPlusVector;
00244
00245
00246 for(Expr::iterator i = e2.begin(); i != e2.end(); i++)
00247 thmPlusVector.push_back(canonMultMtermMterm(e1*(*i)));
00248
00249
00250 Theorem thmPlus1 = d_theoryArith->substitutivityRule(e2.getOp(), thmPlusVector);
00251
00252
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 ArithTheoremProducer::canonCombineLikeTerms(const std::vector<Expr> & sumExprs) {
00435
00436 Rational constant = 0;
00437 MonomMap sumHashMap;
00438 vector<Expr> sumKids;
00439
00440
00441 std::vector<Expr>::const_iterator i = sumExprs.begin();
00442 std::vector<Expr>::const_iterator i_end = sumExprs.end();
00443 for (; i != i_end; i++) {
00444
00445 Expr mul = *i;
00446
00447
00448 if (mul.isRational())
00449 constant = constant + mul.getRational();
00450 else {
00451
00452 switch (mul.getKind()) {
00453
00454
00455 case MULT: {
00456
00457
00458 DebugAssert(mul.arity() > 1 && mul[0].isRational(),"If sum term is multiplication it must have the first term a rational, and at least another one");
00459
00460
00461 Rational r = mul[0].getRational();
00462
00463
00464 vector<Expr> newKids;
00465
00466 for(Expr::iterator m = mul.begin(); m != mul.end(); m ++) newKids.push_back(*m);
00467
00468 newKids[0] = rat(1);
00469
00470 Expr newMul = multExpr(newKids);
00471
00472
00473 MonomMap::iterator i = sumHashMap.find(newMul);
00474
00475
00476 if (i == sumHashMap.end()) sumHashMap[newMul] = r;
00477
00478 else (*i).second += r;
00479
00480
00481 break;
00482 }
00483
00484 default: {
00485
00486
00487 MonomMap::iterator i = sumHashMap.find(multExpr(rat(1), mul));
00488
00489
00490 if (i == sumHashMap.end()) sumHashMap[multExpr(rat(1), mul)] = 1;
00491 else (*i).second += 1;
00492
00493
00494 break;
00495 }
00496 }
00497 }
00498 }
00499
00500
00501 if (constant != 0) sumKids.push_back(rat(constant));
00502
00503
00504 MonomMap::iterator j = sumHashMap.begin(), jend=sumHashMap.end();
00505 for(; j != jend; j++) {
00506
00507 if ((*j).second != 0) {
00508
00509 vector<Expr> newKids;
00510
00511 for(Expr::iterator m = (*j).first.begin(); m != (*j).first.end(); m ++) newKids.push_back(*m);
00512
00513 newKids[0] = rat((*j).second);
00514
00515 sumKids.push_back(multExpr(newKids));
00516 }
00517 }
00518
00519
00520 if (constant != 0 && sumKids.size() == 1) return sumKids[0];
00521
00522
00523 if (constant == 0 && sumKids.size() == 1) return sumKids[0];
00524
00525
00526 if (constant == 0 && sumKids.size() == 0) return rat(0);
00527
00528
00529 return plusExpr(sumKids);
00530 }
00531
00532 Expr ArithTheoremProducer::canonMultLeafOrPowOrMultPlus(const Expr & e1,
00533 const Expr & e2)
00534 {
00535 DebugAssert(e2.getKind() == PLUS, "");
00536
00537
00538
00539
00540
00541
00542 std::vector<Expr> sumExprs;
00543
00544 Expr::iterator i = e2.begin();
00545 for (; i != e2.end(); ++i) {
00546 sumExprs.push_back(canonMultMtermMterm(e1 * (*i)).getRHS());
00547 }
00548 return canonCombineLikeTerms(sumExprs);
00549 }
00550
00551 Expr ArithTheoremProducer::canonMultPlusPlus(const Expr & e1,
00552 const Expr & e2)
00553 {
00554 DebugAssert(e1.getKind() == PLUS && e2.getKind() == PLUS, "");
00555
00556
00557
00558 std::vector<Expr> sumExprs;
00559
00560 Expr::iterator i = e1.begin();
00561 for (; i != e1.end(); ++i) {
00562 Expr::iterator j = e2.begin();
00563 for (; j != e2.end(); ++j) {
00564 sumExprs.push_back(canonMultMtermMterm((*i) * (*j)).getRHS());
00565 }
00566 }
00567 return canonCombineLikeTerms(sumExprs);
00568 }
00569
00570
00571
00572
00573
00574 Theorem ArithTheoremProducer::canonMultMtermMterm(const Expr& e) {
00575
00576
00577 if(CHECK_PROOFS) {
00578 CHECK_SOUND(isMult(e) && e.arity() == 2, "canonMultMtermMterm: e = " + e.toString());
00579 }
00580
00581
00582 Proof pf;
00583
00584
00585 Expr rhs;
00586
00587
00588 const Expr& e1 = e[0];
00589 const Expr& e2 = e[1];
00590
00591
00592 string cmmm = "canon_mult_mterm_mterm";
00593
00594 if (e1.isRational()) {
00595
00596 const Rational& c = e1.getRational();
00597 if (c == 0)
00598 return canonMultZero(e2);
00599 else if (c == 1)
00600 return canonMultOne(e2);
00601 else {
00602 switch (e2.getKind()) {
00603 case RATIONAL_EXPR :
00604
00605 return canonMultConstConst(e1,e2);
00606 break;
00607
00608 case POW:
00609
00610
00611 return d_theoryArith->reflexivityRule (e);
00612
00613 break;
00614 case MULT:
00615 rhs = canonMultConstMult(e1,e2);
00616 if(withProof()) pf = newPf(cmmm,e,rhs);
00617 return newRWTheorem(e, rhs, Assumptions::emptyAssump(), pf);
00618 break;
00619 case PLUS:
00620 rhs = canonMultConstPlus(e1,e2);
00621 if(withProof()) pf = newPf(cmmm,e,rhs);
00622 return newRWTheorem(e, rhs, Assumptions::emptyAssump(), pf);
00623 break;
00624 default:
00625
00626
00627 return d_theoryArith->reflexivityRule(e);
00628 break;
00629 }
00630 }
00631 }
00632 else if (e1.getKind() == POW) {
00633 switch (e2.getKind()) {
00634 case RATIONAL_EXPR:
00635
00636 return canonMultMtermMterm(e2 * e1);
00637 break;
00638 case POW:
00639 rhs = canonMultPowPow(e1,e2);
00640 if(withProof()) pf = newPf(cmmm,e,rhs);
00641 return newRWTheorem(e,rhs, Assumptions::emptyAssump(), pf);
00642 break;
00643 case MULT:
00644 rhs = canonMultLeafOrPowMult(e1,e2);
00645 if(withProof()) pf = newPf(cmmm,e,rhs);
00646 return newRWTheorem(e, rhs, Assumptions::emptyAssump(), pf);
00647 break;
00648 case PLUS:
00649 rhs = canonMultLeafOrPowOrMultPlus(e1,e2);
00650 if(withProof()) pf = newPf(cmmm,e,rhs);
00651 return newRWTheorem(e, rhs, Assumptions::emptyAssump(), pf);
00652 break;
00653 default:
00654 rhs = canonMultPowLeaf(e1,e2);
00655 if(withProof()) pf = newPf(cmmm,e,rhs);
00656 return newRWTheorem(e,rhs, Assumptions::emptyAssump(), pf);
00657 break;
00658 }
00659 }
00660 else if (e1.getKind() == MULT) {
00661 switch (e2.getKind()) {
00662 case RATIONAL_EXPR:
00663 case POW:
00664
00665 return canonMultMtermMterm(e2 * e1);
00666 break;
00667 case MULT:
00668 {
00669
00670 Expr result = e2;
00671 Expr::iterator i = e1.begin();
00672 for (; i != e1.end(); ++i) {
00673 result = canonMultMtermMterm((*i) * result).getRHS();
00674 }
00675 if(withProof()) pf = newPf(cmmm,e,result);
00676 return newRWTheorem(e, result, Assumptions::emptyAssump(), pf);
00677 }
00678 break;
00679 case PLUS:
00680 rhs = canonMultLeafOrPowOrMultPlus(e1,e2);
00681 if(withProof()) pf = newPf(cmmm,e,rhs);
00682 return newRWTheorem(e,rhs, Assumptions::emptyAssump(), pf);
00683 break;
00684 default:
00685
00686
00687 return canonMultMtermMterm(e2 * e1);
00688 break;
00689 }
00690 }
00691 else if (e1.getKind() == PLUS) {
00692 switch (e2.getKind()) {
00693 case RATIONAL_EXPR:
00694 case POW:
00695 case MULT:
00696
00697 return canonMultMtermMterm(e2 * e1);
00698 break;
00699 case PLUS:
00700 rhs = canonMultPlusPlus(e1,e2);
00701 if(withProof()) pf = newPf(cmmm,e,rhs);
00702 return newRWTheorem(e, rhs, Assumptions::emptyAssump(), pf);
00703 break;
00704 default:
00705
00706
00707 return canonMultMtermMterm(e2 * e1);
00708 break;
00709 }
00710 }
00711 else {
00712
00713 switch (e2.getKind()) {
00714 case RATIONAL_EXPR:
00715
00716 return canonMultMtermMterm(e2 * e1);
00717 break;
00718 case POW:
00719 rhs = canonMultPowLeaf(e2,e1);
00720 if(withProof()) pf = newPf(cmmm,e,rhs);
00721 return newRWTheorem(e, rhs, Assumptions::emptyAssump(), pf);
00722 break;
00723 case MULT:
00724 rhs = canonMultLeafOrPowMult(e1,e2);;
00725 if(withProof()) pf = newPf(cmmm,e,rhs);
00726 return newRWTheorem(e, rhs, Assumptions::emptyAssump(), pf);
00727 break;
00728 case PLUS:
00729 rhs = canonMultLeafOrPowOrMultPlus(e1,e2);
00730 if(withProof()) pf = newPf(cmmm,e,rhs);
00731 return newRWTheorem(e, rhs, Assumptions::emptyAssump(), pf);
00732 break;
00733 default:
00734
00735 rhs = canonMultLeafLeaf(e1,e2);
00736 if(withProof()) pf = newPf(cmmm,e,rhs);
00737 return newRWTheorem(e, rhs, Assumptions::emptyAssump(), pf);
00738 break;
00739 }
00740 }
00741 FatalAssert(false, "Unreachable");
00742 return newRWTheorem(e, rhs, Assumptions::emptyAssump(), pf);
00743 }
00744
00745
00746 Theorem ArithTheoremProducer::canonPlus(const Expr& e)
00747 {
00748
00749 Proof pf;
00750
00751
00752 DebugAssert(e.getKind() == PLUS, "");
00753
00754
00755 std::vector<Expr> sumKids;
00756 Expr::iterator i = e.begin();
00757 for(; i != e.end(); ++i) {
00758 if ((*i).getKind() != PLUS)
00759 sumKids.push_back(*i);
00760 else {
00761
00762 Expr::iterator j = (*i).begin();
00763 for(; j != (*i).end(); ++j)
00764 sumKids.push_back(*j);
00765 }
00766 }
00767
00768
00769 Expr val = canonCombineLikeTerms(sumKids);
00770
00771
00772 if (withProof()) {
00773 pf = newPf("canon_plus", e, val);
00774 }
00775
00776
00777 return newRWTheorem(e, val, Assumptions::emptyAssump(), pf);
00778 }
00779
00780
00781 Theorem ArithTheoremProducer::canonMult(const Expr& e)
00782 {
00783
00784 Proof pf;
00785
00786
00787 DebugAssert(e.getKind() == MULT && e.arity() > 1, "");
00788
00789
00790 Expr::iterator i = e.begin();
00791
00792
00793 Expr result = *i;
00794
00795
00796 ++i;
00797
00798
00799 for (; i != e.end(); ++i) {
00800
00801 result = canonMultMtermMterm(result * (*i)).getRHS();
00802 }
00803
00804
00805 if (withProof()) {
00806 pf = newPf("canon_mult", e,result);
00807 }
00808
00809
00810 return newRWTheorem(e, result, Assumptions::emptyAssump(), pf);
00811 }
00812
00813
00814 Theorem
00815 ArithTheoremProducer::canonInvertConst(const Expr& e)
00816 {
00817 if(CHECK_PROOFS)
00818 CHECK_SOUND(isRational(e), "expecting a rational: e = "+e.toString());
00819
00820 Proof pf;
00821
00822 if (withProof()) {
00823 pf = newPf("canon_invert_const", e);
00824 }
00825 const Rational& er = e.getRational();
00826 return newRWTheorem((rat(1)/e), rat(er==0? 0 : (1/er)), Assumptions::emptyAssump(), pf);
00827 }
00828
00829
00830 Theorem
00831 ArithTheoremProducer::canonInvertLeaf(const Expr& e)
00832 {
00833 Proof pf;
00834
00835 if (withProof()) {
00836 pf = newPf("canon_invert_leaf", e);
00837 }
00838 return newRWTheorem((rat(1)/e), powExpr(rat(-1), e), Assumptions::emptyAssump(), pf);
00839 }
00840
00841
00842 Theorem
00843 ArithTheoremProducer::canonInvertPow(const Expr& e)
00844 {
00845 DebugAssert(e.getKind() == POW, "expecting a rational"+e[0].toString());
00846
00847 Proof pf;
00848
00849 if (withProof()) {
00850 pf = newPf("canon_invert_pow", e);
00851 }
00852 if (e[0].getRational() == -1)
00853 return newRWTheorem((rat(1)/e), e[1], Assumptions::emptyAssump(), pf);
00854 else
00855 return newRWTheorem((rat(1)/e),
00856 powExpr(rat(-e[0].getRational()), e),
00857 Assumptions::emptyAssump(),
00858 pf);
00859 }
00860
00861 Theorem
00862 ArithTheoremProducer::canonInvertMult(const Expr& e)
00863 {
00864 DebugAssert(e.getKind() == MULT, "expecting a rational"+e[0].toString());
00865
00866 Proof pf;
00867
00868 if (withProof()) {
00869 pf = newPf("canon_invert_mult", e);
00870 }
00871
00872 DebugAssert(e.arity() > 1, "MULT should have arity > 1"+e.toString());
00873 Expr result = canonInvert(e[0]).getRHS();
00874 for (int i = 1; i < e.arity(); ++i) {
00875 result =
00876 canonMultMtermMterm(result * canonInvert(e[i]).getRHS()).getRHS();
00877 }
00878 return newRWTheorem((rat(1)/e), result, Assumptions::emptyAssump(), pf);
00879 }
00880
00881
00882
00883
00884 Theorem
00885 ArithTheoremProducer::canonInvert(const Expr& e)
00886 {
00887 DebugAssert(e.getKind() != PLUS,
00888 "Cannot do inverse on a PLUS"+e.toString());
00889 switch (e.getKind()) {
00890 case RATIONAL_EXPR:
00891 return canonInvertConst(e);
00892 break;
00893 case POW:
00894 return canonInvertPow(e);
00895 break;
00896 case MULT:
00897 return canonInvertMult(e);
00898 break;
00899 default:
00900
00901 return canonInvertLeaf(e);
00902 break;
00903 }
00904 }
00905
00906
00907 Theorem ArithTheoremProducer::canonDivide(const Expr& e)
00908 {
00909
00910 DebugAssert(e.getKind() == DIVIDE, "Expecting Divide"+e.toString());
00911
00912
00913 Proof pf;
00914
00915
00916 if (withProof()) {
00917 pf = newPf("canon_invert_divide", e);
00918 }
00919
00920
00921 Theorem thm = newRWTheorem(e, e[0]*(canonInvert(e[1]).getRHS()), Assumptions::emptyAssump(), pf);
00922
00923
00924 return d_theoryArith->transitivityRule(thm, canonMult(thm.getRHS()));
00925 }
00926
00927
00928
00929
00930 Theorem
00931 ArithTheoremProducer::canonMultTermConst(const Expr& c, const Expr& t) {
00932 Proof pf;
00933 if(CHECK_PROOFS) {
00934 CHECK_SOUND(isRational(c),
00935 CLASS_NAME "::canonMultTermConst:\n "
00936 "c is not a constant: " + c.toString());
00937 }
00938 if(withProof()) pf = newPf("canon_mult_term_const", c, t);
00939 return newRWTheorem((t*c), (c*t), Assumptions::emptyAssump(), pf);
00940 }
00941
00942
00943
00944 Theorem
00945 ArithTheoremProducer::canonMultTerm1Term2(const Expr& t1, const Expr& t2) {
00946
00947
00948 if(CHECK_PROOFS) {
00949 CHECK_SOUND(false, "Fatal Error: We don't support multiplication"
00950 "of two non constant terms at this time "
00951 + t1.toString() + " and " + t2.toString());
00952 }
00953 return Theorem();
00954 }
00955
00956
00957
00958 Theorem ArithTheoremProducer::canonMultZero(const Expr& e) {
00959 Proof pf;
00960 if(withProof()) pf = newPf("canon_mult_zero", e);
00961 return newRWTheorem((rat(0)*e), rat(0), Assumptions::emptyAssump(), pf);
00962 }
00963
00964
00965
00966
00967 Theorem ArithTheoremProducer::canonMultOne(const Expr& e) {
00968
00969
00970 Proof pf;
00971 if(withProof()) pf = newPf("canon_mult_one", e);
00972
00973
00974 if (d_theoryArith->isLeaf(e)) return d_theoryArith->reflexivityRule (rat(1)*e);
00975
00976
00977 return newRWTheorem((rat(1)*e), e, Assumptions::emptyAssump(), pf);
00978 }
00979
00980
00981
00982 Theorem
00983 ArithTheoremProducer::canonMultConstConst(const Expr& c1, const Expr& c2) {
00984 Proof pf;
00985 if(CHECK_PROOFS) {
00986 CHECK_SOUND(isRational(c1),
00987 CLASS_NAME "::canonMultConstConst:\n "
00988 "c1 is not a constant: " + c1.toString());
00989 CHECK_SOUND(isRational(c2),
00990 CLASS_NAME "::canonMultConstConst:\n "
00991 "c2 is not a constant: " + c2.toString());
00992 }
00993 if(withProof()) pf = newPf("canon_mult_const_const", c1, c2);
00994 return
00995 newRWTheorem((c1*c2), rat(c1.getRational()*c2.getRational()), Assumptions::emptyAssump(), pf);
00996 }
00997
00998
00999
01000 Theorem
01001 ArithTheoremProducer::canonMultConstTerm(const Expr& c1,
01002 const Expr& c2,const Expr& t) {
01003 Proof pf;
01004 if(CHECK_PROOFS) {
01005 CHECK_SOUND(isRational(c1),
01006 CLASS_NAME "::canonMultConstTerm:\n "
01007 "c1 is not a constant: " + c1.toString());
01008 CHECK_SOUND(isRational(c2),
01009 CLASS_NAME "::canonMultConstTerm:\n "
01010 "c2 is not a constant: " + c2.toString());
01011 }
01012
01013 if(withProof()) pf = newPf("canon_mult_const_term", c1, c2, t);
01014 return
01015 newRWTheorem(c1*(c2*t), rat(c1.getRational()*c2.getRational())*t, Assumptions::emptyAssump(), pf);
01016 }
01017
01018
01019
01020 Theorem
01021 ArithTheoremProducer::canonMultConstSum(const Expr& c1, const Expr& sum) {
01022 Proof pf;
01023 std::vector<Expr> sumKids;
01024
01025 if(CHECK_PROOFS) {
01026 CHECK_SOUND(isRational(c1),
01027 CLASS_NAME "::canonMultConstTerm:\n "
01028 "c1 is not a constant: " + c1.toString());
01029 CHECK_SOUND(PLUS == sum.getKind(),
01030 CLASS_NAME "::canonMultConstTerm:\n "
01031 "the kind must be a PLUS: " + sum.toString());
01032 }
01033 Expr::iterator i = sum.begin();
01034 for(; i != sum.end(); ++i)
01035 sumKids.push_back(c1*(*i));
01036 Expr ret = plusExpr(sumKids);
01037 if(withProof()) pf = newPf("canon_mult_const_sum", c1, sum, ret);
01038 return newRWTheorem((c1*sum),ret , Assumptions::emptyAssump(), pf);
01039 }
01040
01041
01042
01043 Theorem ArithTheoremProducer::canonPowConst(const Expr& e) {
01044 if(CHECK_PROOFS) {
01045 CHECK_SOUND(e.getKind() == POW && e.arity() == 2
01046 && e[0].isRational() && e[1].isRational(),
01047 "ArithTheoremProducer::canonPowConst("+e.toString()+")");
01048 }
01049 const Rational& p = e[0].getRational();
01050 const Rational& base = e[1].getRational();
01051 if(CHECK_PROOFS) {
01052 CHECK_SOUND(p.isInteger(),
01053 "ArithTheoremProducer::canonPowConst("+e.toString()+")");
01054 }
01055 Expr res;
01056 if (base == 0 && p < 0) {
01057 res = rat(0);
01058 }
01059 else res = rat(pow(p, base));
01060 Proof pf;
01061 if(withProof())
01062 pf = newPf("canon_pow_const", e);
01063 return newRWTheorem(e, res, Assumptions::emptyAssump(), pf);
01064 }
01065
01066
01067
01068
01069 Theorem
01070 ArithTheoremProducer::canonFlattenSum(const Expr& e) {
01071 Proof pf;
01072 std::vector<Expr> sumKids;
01073 if(CHECK_PROOFS) {
01074 CHECK_SOUND(PLUS == e.getKind(),
01075 CLASS_NAME "::canonFlattenSum:\n"
01076 "input must be a PLUS:" + e.toString());
01077 }
01078
01079 Expr::iterator i = e.begin();
01080 for(; i != e.end(); ++i){
01081 if (PLUS != (*i).getKind())
01082 sumKids.push_back(*i);
01083 else {
01084 Expr::iterator j = (*i).begin();
01085 for(; j != (*i).end(); ++j)
01086 sumKids.push_back(*j);
01087 }
01088 }
01089 Expr ret = plusExpr(sumKids);
01090 if(withProof()) pf = newPf("canon_flatten_sum", e,ret);
01091 return newRWTheorem(e,ret, Assumptions::emptyAssump(), pf);
01092 }
01093
01094
01095
01096 Theorem
01097 ArithTheoremProducer::canonComboLikeTerms(const Expr& e) {
01098 Proof pf;
01099 std::vector<Expr> sumKids;
01100 ExprMap<Rational> sumHashMap;
01101 Rational constant = 0;
01102
01103 if(CHECK_PROOFS) {
01104 Expr::iterator k = e.begin();
01105 for(; k != e.end(); ++k)
01106 CHECK_SOUND(!isPlus(*k),
01107 CLASS_NAME "::canonComboLikeTerms:\n"
01108 "input must be a flattened PLUS:" + k->toString());
01109 }
01110 Expr::iterator i = e.begin();
01111 for(; i != e.end(); ++i){
01112 if(i->isRational())
01113 constant = constant + i->getRational();
01114 else {
01115 if (!isMult(*i)) {
01116 if(0 == sumHashMap.count((*i)))
01117 sumHashMap[*i] = 1;
01118 else
01119 sumHashMap[*i] += 1;
01120 }
01121 else {
01122 if(0 == sumHashMap.count((*i)[1]))
01123 sumHashMap[(*i)[1]] = (*i)[0].getRational();
01124 else
01125 sumHashMap[(*i)[1]] = sumHashMap[(*i)[1]] + (*i)[0].getRational();
01126 }
01127 }
01128 }
01129
01130 sumKids.push_back(rat(constant));
01131 ExprMap<Rational>::iterator j = sumHashMap.begin();
01132 for(; j != sumHashMap.end(); ++j) {
01133 if(0 == (*j).second)
01134 ;
01135 else if (1 == (*j).second)
01136 sumKids.push_back((*j).first);
01137 else
01138 sumKids.push_back(rat((*j).second) * (*j).first);
01139 }
01140
01141
01142
01143
01144 Expr ret;
01145 if(2 == sumKids.size() && 0 == constant) ret = sumKids[1];
01146 else if (1 == sumKids.size()) ret = sumKids[0];
01147 else ret = plusExpr(sumKids);
01148
01149 if(withProof()) pf = newPf("canon_combo_like_terms",e,ret);
01150 return newRWTheorem(e, ret, Assumptions::emptyAssump(), pf);
01151 }
01152
01153
01154
01155 Theorem ArithTheoremProducer::multEqZero(const Expr& expr)
01156 {
01157 if (CHECK_PROOFS) {
01158 CHECK_SOUND(expr.isEq() && expr[0].isRational() &&
01159 expr[0].getRational() == 0 &&
01160 isMult(expr[1]) && expr[1].arity() > 1,
01161 "multEqZero invariant violated"+expr.toString());
01162 }
01163 Proof pf;
01164 vector<Expr> kids;
01165 Expr::iterator i = expr[1].begin(), iend = expr[1].end();
01166 for (; i != iend; ++i) {
01167 kids.push_back(rat(0).eqExpr(*i));
01168 }
01169 if (withProof()) {
01170 pf = newPf("multEqZero", expr);
01171 }
01172 return newRWTheorem(expr, Expr(OR, kids), Assumptions::emptyAssump(), pf);
01173 }
01174
01175
01176
01177
01178 Theorem ArithTheoremProducer::powEqZero(const Expr& expr)
01179 {
01180 if (CHECK_PROOFS) {
01181 CHECK_SOUND(expr.isEq() && expr[0].isRational() &&
01182 expr[0].getRational() == 0 &&
01183 isPow(expr[1]) && expr[1].arity() == 2 &&
01184 expr[1][0].isRational(),
01185 "powEqZero invariant violated"+expr.toString());
01186 }
01187 Proof pf;
01188 if (withProof()) {
01189 pf = newPf("powEqZero", expr);
01190 }
01191 Rational r = expr[1][0].getRational();
01192 Expr res;
01193 if (r <= 0) {
01194 res = d_em->falseExpr();
01195 }
01196 else {
01197 res = rat(0).eqExpr(expr[1][1]);
01198 }
01199 return newRWTheorem(expr, res, Assumptions::emptyAssump(), pf);
01200 }
01201
01202
01203
01204
01205 Theorem ArithTheoremProducer::elimPower(const Expr& expr)
01206 {
01207 if (CHECK_PROOFS) {
01208 CHECK_SOUND(expr.isEq() && isPow(expr[0]) &&
01209 isPow(expr[1]) &&
01210 isIntegerConst(expr[0][0]) &&
01211 expr[0][0].getRational() > 0 &&
01212 expr[0][0] == expr[1][0],
01213 "elimPower invariant violated"+expr.toString());
01214 }
01215 Proof pf;
01216 if (withProof()) {
01217 pf = newPf("elimPower", expr);
01218 }
01219 Rational r = expr[0][0].getRational();
01220 Expr res = expr[0][1].eqExpr(expr[1][1]);
01221 if (r % 2 == 0) {
01222 res = res.orExpr(expr[0][1].eqExpr(-expr[1][1]));
01223 }
01224 return newRWTheorem(expr, res, Assumptions::emptyAssump(), pf);
01225 }
01226
01227
01228
01229
01230 Theorem ArithTheoremProducer::elimPowerConst(const Expr& expr, const Rational& root)
01231 {
01232 if (CHECK_PROOFS) {
01233 CHECK_SOUND(expr.isEq() && isPow(expr[0]) &&
01234 isIntegerConst(expr[0][0]) &&
01235 expr[0][0].getRational() > 0 &&
01236 expr[1].isRational() &&
01237 pow(expr[0][0].getRational(), root) == expr[1].getRational(),
01238 "elimPowerConst invariant violated"+expr.toString());
01239 }
01240 Proof pf;
01241 if (withProof()) {
01242 pf = newPf("elimPowerConst", expr, rat(root));
01243 }
01244 Rational r = expr[0][0].getRational();
01245 Expr res = expr[0][1].eqExpr(rat(root));
01246 if (r % 2 == 0) {
01247 res = res.orExpr(expr[0][1].eqExpr(rat(-root)));
01248 }
01249 return newRWTheorem(expr, res, Assumptions::emptyAssump(), pf);
01250 }
01251
01252
01253
01254 Theorem ArithTheoremProducer::evenPowerEqNegConst(const Expr& expr)
01255 {
01256 if (CHECK_PROOFS) {
01257 CHECK_SOUND(expr.isEq() && isPow(expr[0]) &&
01258 expr[1].isRational() &&
01259 isIntegerConst(expr[0][0]) &&
01260 expr[0][0].getRational() % 2 == 0 &&
01261 expr[1].getRational() < 0,
01262 "evenPowerEqNegConst invariant violated"+expr.toString());
01263 }
01264 Proof pf;
01265 if (withProof()) {
01266 pf = newPf("evenPowerEqNegConst", expr);
01267 }
01268 return newRWTheorem(expr, d_em->falseExpr(), Assumptions::emptyAssump(), pf);
01269 }
01270
01271
01272
01273 Theorem ArithTheoremProducer::intEqIrrational(const Expr& expr, const Theorem& isIntx)
01274 {
01275 if (CHECK_PROOFS) {
01276 CHECK_SOUND(expr.isEq() && isPow(expr[0]) &&
01277 expr[1].isRational() &&
01278 expr[1].getRational() != 0 &&
01279 isIntegerConst(expr[0][0]) &&
01280 expr[0][0].getRational() > 0 &&
01281 ratRoot(expr[1].getRational(), expr[0][0].getRational().getUnsigned()) == 0,
01282 "intEqIrrational invariant violated"+expr.toString());
01283 CHECK_SOUND(isIntPred(isIntx.getExpr()) && isIntx.getExpr()[0] == expr[0][1],
01284 "ArithTheoremProducerOld::intEqIrrational:\n "
01285 "wrong integrality constraint:\n expr = "
01286 +expr.toString()+"\n isIntx = "
01287 +isIntx.getExpr().toString());
01288 }
01289 const Assumptions& assump(isIntx.getAssumptionsRef());
01290 Proof pf;
01291 if (withProof()) {
01292 pf = newPf("int_eq_irr", expr, isIntx.getProof());
01293 }
01294 return newRWTheorem(expr, d_em->falseExpr(), assump, pf);
01295 }
01296
01297
01298
01299
01300 Theorem ArithTheoremProducer::constPredicate(const Expr& e) {
01301 if(CHECK_PROOFS) {
01302 CHECK_SOUND(e.arity() == 2 && isRational(e[0]) && isRational(e[1]),
01303 CLASS_NAME "::constPredicate:\n "
01304 "non-const parameters: " + e.toString());
01305 }
01306 Proof pf;
01307 bool result(false);
01308 int kind = e.getKind();
01309 Rational r1 = e[0].getRational(), r2 = e[1].getRational();
01310 switch(kind) {
01311 case EQ:
01312 result = (r1 == r2)?true : false;
01313 break;
01314 case LT:
01315 result = (r1 < r2)?true : false;
01316 break;
01317 case LE:
01318 result = (r1 <= r2)?true : false;
01319 break;
01320 case GT:
01321 result = (r1 > r2)?true : false;
01322 break;
01323 case GE:
01324 result = (r1 >= r2)?true : false;
01325 break;
01326 default:
01327 if(CHECK_PROOFS) {
01328 CHECK_SOUND(false,
01329 "ArithTheoremProducer::constPredicate: wrong kind");
01330 }
01331 break;
01332 }
01333 Expr ret = (result) ? d_em->trueExpr() : d_em->falseExpr();
01334 if(withProof()) pf = newPf("const_predicate", e,ret);
01335 return newRWTheorem(e, ret, Assumptions::emptyAssump(), pf);
01336 }
01337
01338
01339
01340 Theorem ArithTheoremProducer::rightMinusLeft(const Expr& e)
01341 {
01342 Proof pf;
01343 int kind = e.getKind();
01344 if(CHECK_PROOFS) {
01345 CHECK_SOUND((EQ==kind) ||
01346 (LT==kind) ||
01347 (LE==kind) ||
01348 (GE==kind) ||
01349 (GT==kind),
01350 "ArithTheoremProduder::rightMinusLeft: wrong kind");
01351 }
01352 if(withProof()) pf = newPf("right_minus_left",e);
01353 return newRWTheorem(e, Expr(e.getOp(), rat(0), e[1] - e[0]), Assumptions::emptyAssump(), pf);
01354 }
01355
01356
01357 Theorem ArithTheoremProducer::leftMinusRight(const Expr& e)
01358 {
01359 Proof pf;
01360 int kind = e.getKind();
01361 if(CHECK_PROOFS) {
01362 CHECK_SOUND((EQ==kind) ||
01363 (LT==kind) ||
01364 (LE==kind) ||
01365 (GE==kind) ||
01366 (GT==kind),
01367 "ArithTheoremProduder::rightMinusLeft: wrong kind");
01368 }
01369 if(withProof()) pf = newPf("left_minus_right",e);
01370 return newRWTheorem(e, Expr(e.getOp(), e[0] - e[1], rat(0)), Assumptions::emptyAssump(), pf);
01371 }
01372
01373
01374
01375
01376 Theorem ArithTheoremProducer::plusPredicate(const Expr& x,
01377 const Expr& y,
01378 const Expr& z, int kind) {
01379 if(CHECK_PROOFS) {
01380 CHECK_SOUND((EQ==kind) ||
01381 (LT==kind) ||
01382 (LE==kind) ||
01383 (GE==kind) ||
01384 (GT==kind),
01385 "ArithTheoremProduder::plusPredicate: wrong kind");
01386 }
01387 Proof pf;
01388 Expr left = Expr(kind, x, y);
01389 Expr right = Expr(kind, x + z, y + z);
01390 if(withProof()) pf = newPf("plus_predicate",left,right);
01391 return newRWTheorem(left, right, Assumptions::emptyAssump(), pf);
01392 }
01393
01394
01395 Theorem ArithTheoremProducer::multEqn(const Expr& x,
01396 const Expr& y,
01397 const Expr& z) {
01398 Proof pf;
01399 if(CHECK_PROOFS)
01400 CHECK_SOUND(z.isRational() && z.getRational() != 0,
01401 "ArithTheoremProducer::multEqn(): multiplying equation by 0");
01402 if(withProof()) pf = newPf("mult_eqn", x, y, z);
01403 return newRWTheorem(x.eqExpr(y), (x * z).eqExpr(y * z), Assumptions::emptyAssump(), pf);
01404 }
01405
01406
01407
01408 Theorem ArithTheoremProducer::divideEqnNonConst(const Expr& x,
01409 const Expr& y,
01410 const Expr& z) {
01411 Proof pf;
01412 if(withProof()) pf = newPf("mult_eqn_nonconst", x, y, z);
01413 return newRWTheorem(x.eqExpr(y), (z.eqExpr(rat(0))).orExpr((x / z).eqExpr(y / z)),
01414 Assumptions::emptyAssump(), pf);
01415 }
01416
01417
01418
01419
01420 Theorem ArithTheoremProducer::multIneqn(const Expr& e, const Expr& z) {
01421
01422
01423 if(CHECK_PROOFS) {
01424 CHECK_SOUND(isIneq(e), "ArithTheoremProduder::multIneqn: wrong kind");
01425 CHECK_SOUND(z.isRational() && z.getRational() != 0, "ArithTheoremProduder::multIneqn: z must be non-zero rational: " + z.toString());
01426 }
01427
01428
01429 Op op(e.getOp());
01430
01431
01432 Expr ret;
01433
01434 if(0 < z.getRational())
01435 ret = Expr(op, e[0]*z, e[1]*z);
01436 else
01437
01438 switch (e.getKind()) {
01439 case LE: ret = geExpr(e[0]*z, e[1]*z); break;
01440 case LT: ret = gtExpr(e[0]*z, e[1]*z); break;
01441 case GE: ret = leExpr(e[0]*z, e[1]*z); break;
01442 case GT: ret = ltExpr(e[0]*z, e[1]*z); break;
01443 default:
01444
01445 break;
01446 }
01447
01448
01449 Proof pf;
01450 if(withProof()) pf = newPf("mult_ineqn", e, ret);
01451
01452
01453 return newRWTheorem(e, ret, Assumptions::emptyAssump(), pf);
01454 }
01455
01456
01457
01458
01459
01460
01461
01462
01463
01464
01465
01466
01467
01468
01469
01470
01471
01472
01473
01474
01475
01476
01477
01478
01479
01480
01481
01482
01483
01484
01485
01486
01487
01488
01489
01490
01491
01492
01493
01494
01495
01496
01497
01498 Theorem ArithTheoremProducer::flipInequality(const Expr& e)
01499 {
01500 Proof pf;
01501 if(CHECK_PROOFS) {
01502 CHECK_SOUND(isGT(e) || isGE(e),
01503 "ArithTheoremProducer::flipInequality: wrong kind: " +
01504 e.toString());
01505 }
01506
01507 int kind = isGE(e) ? LE : LT;
01508 Expr ret = Expr(kind, e[1], e[0]);
01509 if(withProof()) pf = newPf("flip_inequality", e,ret);
01510 return newRWTheorem(e,ret, Assumptions::emptyAssump(), pf);
01511 }
01512
01513
01514
01515
01516
01517
01518 Theorem ArithTheoremProducer::negatedInequality(const Expr& e)
01519 {
01520 const Expr& ineq = e[0];
01521 if(CHECK_PROOFS) {
01522 CHECK_SOUND(e.isNot(),
01523 "ArithTheoremProducer::negatedInequality: wrong kind: " +
01524 e.toString());
01525 CHECK_SOUND(isIneq(ineq),
01526 "ArithTheoremProducer::negatedInequality: wrong kind: " +
01527 (ineq).toString());
01528 }
01529 Proof pf;
01530 if(withProof()) pf = newPf("negated_inequality", e);
01531
01532 int kind;
01533
01534
01535
01536
01537 kind =
01538 isLT(ineq) ? GE :
01539 isLE(ineq) ? GT :
01540 isGT(ineq) ? LE :
01541 LT;
01542 return newRWTheorem(e, Expr(kind, ineq[0], ineq[1]), Assumptions::emptyAssump(), pf);
01543 }
01544
01545
01546
01547 Theorem ArithTheoremProducer::realShadow(const Theorem& alphaLTt,
01548 const Theorem& tLTbeta)
01549 {
01550 const Expr& expr1 = alphaLTt.getExpr();
01551 const Expr& expr2 = tLTbeta.getExpr();
01552 if(CHECK_PROOFS) {
01553 CHECK_SOUND((isLE(expr1) || isLT(expr1)) &&
01554 (isLE(expr2) || isLT(expr2)),
01555 "ArithTheoremProducer::realShadow: Wrong Kind: " +
01556 alphaLTt.toString() + tLTbeta.toString());
01557
01558 CHECK_SOUND(expr1[1] == expr2[0],
01559 "ArithTheoremProducer::realShadow:"
01560 " t must be same for both inputs: " +
01561 expr1[1].toString() + " , " + expr2[0].toString());
01562 }
01563 Assumptions a(alphaLTt, tLTbeta);
01564 int firstKind = expr1.getKind();
01565 int secondKind = expr2.getKind();
01566 int kind = (firstKind == secondKind) ? firstKind : LT;
01567 Proof pf;
01568 if(withProof()) {
01569 vector<Proof> pfs;
01570 pfs.push_back(alphaLTt.getProof());
01571 pfs.push_back(tLTbeta.getProof());
01572 pf = newPf("real_shadow",expr1, expr2, pfs);
01573 }
01574 return newTheorem(Expr(kind, expr1[0], expr2[1]), a, pf);
01575 }
01576
01577
01578
01579
01580
01581
01582 Theorem ArithTheoremProducer::realShadowEq(const Theorem& alphaLEt,
01583 const Theorem& tLEalpha)
01584 {
01585 const Expr& expr1 = alphaLEt.getExpr();
01586 const Expr& expr2 = tLEalpha.getExpr();
01587 if(CHECK_PROOFS) {
01588 CHECK_SOUND(isLE(expr1) && isLE(expr2),
01589 "ArithTheoremProducer::realShadowLTLE: Wrong Kind: " +
01590 alphaLEt.toString() + tLEalpha.toString());
01591
01592 CHECK_SOUND(expr1[1] == expr2[0],
01593 "ArithTheoremProducer::realShadowLTLE:"
01594 " t must be same for both inputs: " +
01595 alphaLEt.toString() + " , " + tLEalpha.toString());
01596
01597 CHECK_SOUND(expr1[0] == expr2[1],
01598 "ArithTheoremProducer::realShadowLTLE:"
01599 " alpha must be same for both inputs: " +
01600 alphaLEt.toString() + " , " + tLEalpha.toString());
01601 }
01602 Assumptions a(alphaLEt, tLEalpha);
01603 Proof pf;
01604 if(withProof()) {
01605 vector<Proof> pfs;
01606 pfs.push_back(alphaLEt.getProof());
01607 pfs.push_back(tLEalpha.getProof());
01608 pf = newPf("real_shadow_eq", alphaLEt.getExpr(), tLEalpha.getExpr(), pfs);
01609 }
01610 return newRWTheorem(expr1[0], expr1[1], a, pf);
01611 }
01612
01613 Theorem
01614 ArithTheoremProducer::finiteInterval(const Theorem& aLEt,
01615 const Theorem& tLEac,
01616 const Theorem& isInta,
01617 const Theorem& isIntt) {
01618 const Expr& e1 = aLEt.getExpr();
01619 const Expr& e2 = tLEac.getExpr();
01620 if(CHECK_PROOFS) {
01621 CHECK_SOUND(isLE(e1) && isLE(e2),
01622 "ArithTheoremProducer::finiteInterval:\n e1 = "
01623 +e1.toString()+"\n e2 = "+e2.toString());
01624
01625 CHECK_SOUND(e1[1] == e2[0],
01626 "ArithTheoremProducer::finiteInterval:\n e1 = "
01627 +e1.toString()+"\n e2 = "+e2.toString());
01628
01629 CHECK_SOUND(isPlus(e2[1]) && e2[1].arity() == 2,
01630 "ArithTheoremProducer::finiteInterval:\n e1 = "
01631 +e1.toString()+"\n e2 = "+e2.toString());
01632
01633 CHECK_SOUND(e1[0] == e2[1][0],
01634 "ArithTheoremProducer::finiteInterval:\n e1 = "
01635 +e1.toString()+"\n e2 = "+e2.toString());
01636
01637 CHECK_SOUND(e2[1][1].isRational() && e2[1][1].getRational().isInteger()
01638 && e2[1][1].getRational() >= 1,
01639 "ArithTheoremProducer::finiteInterval:\n e1 = "
01640 +e1.toString()+"\n e2 = "+e2.toString());
01641
01642 const Expr& isIntaExpr = isInta.getExpr();
01643 const Expr& isInttExpr = isIntt.getExpr();
01644 CHECK_SOUND(isIntPred(isIntaExpr) && isIntaExpr[0] == e1[0],
01645 "Wrong integrality constraint:\n e1 = "
01646 +e1.toString()+"\n isInta = "+isIntaExpr.toString());
01647 CHECK_SOUND(isIntPred(isInttExpr) && isInttExpr[0] == e1[1],
01648 "Wrong integrality constraint:\n e1 = "
01649 +e1.toString()+"\n isIntt = "+isInttExpr.toString());
01650 }
01651 vector<Theorem> thms;
01652 thms.push_back(aLEt);
01653 thms.push_back(tLEac);
01654 thms.push_back(isInta);
01655 thms.push_back(isIntt);
01656 Assumptions a(thms);
01657 Proof pf;
01658 if(withProof()) {
01659 vector<Expr> es;
01660 vector<Proof> pfs;
01661 es.push_back(e1);
01662 es.push_back(e2);
01663 es.push_back(isInta.getExpr());
01664 es.push_back(isIntt.getExpr());
01665 pfs.push_back(aLEt.getProof());
01666 pfs.push_back(tLEac.getProof());
01667 pfs.push_back(isInta.getProof());
01668 pfs.push_back(isIntt.getProof());
01669 pf = newPf("finite_interval", es, pfs);
01670 }
01671
01672 Expr g(grayShadow(e1[1], e1[0], 0, e2[1][1].getRational()));
01673 return newTheorem(g, a, pf);
01674 }
01675
01676
01677
01678 Theorem ArithTheoremProducer::darkGrayShadow2ab(const Theorem& betaLEbx,
01679 const Theorem& axLEalpha,
01680 const Theorem& isIntAlpha,
01681 const Theorem& isIntBeta,
01682 const Theorem& isIntx) {
01683 const Expr& expr1 = betaLEbx.getExpr();
01684 const Expr& expr2 = axLEalpha.getExpr();
01685 const Expr& isIntAlphaExpr = isIntAlpha.getExpr();
01686 const Expr& isIntBetaExpr = isIntBeta.getExpr();
01687 const Expr& isIntxExpr = isIntx.getExpr();
01688
01689 if(CHECK_PROOFS) {
01690 CHECK_SOUND(isLE(expr1) && isLE(expr2),
01691 "ArithTheoremProducer::darkGrayShadow2ab: Wrong Kind: " +
01692 betaLEbx.toString() + axLEalpha.toString());
01693 }
01694
01695 const Expr& beta = expr1[0];
01696 const Expr& bx = expr1[1];
01697 const Expr& ax = expr2[0];
01698 const Expr& alpha = expr2[1];
01699 Rational a = isMult(ax)? ax[0].getRational() : 1;
01700 Rational b = isMult(bx)? bx[0].getRational() : 1;
01701 const Expr& x = isMult(ax)? ax[1] : ax;
01702
01703 if(CHECK_PROOFS) {
01704
01705 CHECK_SOUND(isIntPred(isIntAlphaExpr) && isIntAlphaExpr[0] == alpha,
01706 "ArithTheoremProducer::darkGrayShadow2ab:\n "
01707 "wrong integrality constraint:\n alpha = "
01708 +alpha.toString()+"\n isIntAlpha = "
01709 +isIntAlphaExpr.toString());
01710 CHECK_SOUND(isIntPred(isIntBetaExpr) && isIntBetaExpr[0] == beta,
01711 "ArithTheoremProducer::darkGrayShadow2ab:\n "
01712 "wrong integrality constraint:\n beta = "
01713 +beta.toString()+"\n isIntBeta = "
01714 +isIntBetaExpr.toString());
01715 CHECK_SOUND(isIntPred(isIntxExpr) && isIntxExpr[0] == x,
01716 "ArithTheoremProducer::darkGrayShadow2ab:\n "
01717 "wrong integrality constraint:\n x = "
01718 +x.toString()+"\n isIntx = "
01719 +isIntxExpr.toString());
01720
01721 CHECK_SOUND(!isMult(ax) || ax.arity() == 2,
01722 "ArithTheoremProducer::darkGrayShadow2ab:\n ax<=alpha: " +
01723 axLEalpha.toString());
01724 CHECK_SOUND(!isMult(bx) || (bx.arity() == 2 && bx[1] == x),
01725 "ArithTheoremProducer::darkGrayShadow2ab:\n beta<=bx: "
01726 +betaLEbx.toString()
01727 +"\n ax<=alpha: "+ axLEalpha.toString());
01728 CHECK_SOUND(1 <= a && a <= b && 2 <= b,
01729 "ArithTheoremProducer::darkGrayShadow2ab:\n beta<=bx: "
01730 +betaLEbx.toString()
01731 +"\n ax<=alpha: "+ axLEalpha.toString());
01732 }
01733 vector<Theorem> thms;
01734 thms.push_back(betaLEbx);
01735 thms.push_back(axLEalpha);
01736 thms.push_back(isIntAlpha);
01737 thms.push_back(isIntBeta);
01738 thms.push_back(isIntx);
01739 Assumptions A(thms);
01740
01741 Expr bAlpha = multExpr(rat(b), alpha);
01742 Expr aBeta = multExpr(rat(a), beta);
01743 Expr t = minusExpr(bAlpha, aBeta);
01744 Expr d = darkShadow(rat(a*b-1), t);
01745 Expr g = grayShadow(ax, alpha, -a+1, 0);
01746
01747 Proof pf;
01748 if(withProof()) {
01749 vector<Expr> exprs;
01750 exprs.push_back(expr1);
01751 exprs.push_back(expr2);
01752 exprs.push_back(d);
01753 exprs.push_back(g);
01754
01755 vector<Proof> pfs;
01756 pfs.push_back(betaLEbx.getProof());
01757 pfs.push_back(axLEalpha.getProof());
01758 pfs.push_back(isIntAlpha.getProof());
01759 pfs.push_back(isIntBeta.getProof());
01760 pfs.push_back(isIntx.getProof());
01761
01762 pf = newPf("dark_grayshadow_2ab", exprs, pfs);
01763 }
01764
01765 return newTheorem((d || g) && (!d || !g), A, pf);
01766 }
01767
01768
01769 Theorem ArithTheoremProducer::darkGrayShadow2ba(const Theorem& betaLEbx,
01770 const Theorem& axLEalpha,
01771 const Theorem& isIntAlpha,
01772 const Theorem& isIntBeta,
01773 const Theorem& isIntx) {
01774 const Expr& expr1 = betaLEbx.getExpr();
01775 const Expr& expr2 = axLEalpha.getExpr();
01776 const Expr& isIntAlphaExpr = isIntAlpha.getExpr();
01777 const Expr& isIntBetaExpr = isIntBeta.getExpr();
01778 const Expr& isIntxExpr = isIntx.getExpr();
01779
01780 if(CHECK_PROOFS) {
01781 CHECK_SOUND(isLE(expr1) && isLE(expr2),
01782 "ArithTheoremProducer::darkGrayShadow2ba: Wrong Kind: " +
01783 betaLEbx.toString() + axLEalpha.toString());
01784 }
01785
01786 const Expr& beta = expr1[0];
01787 const Expr& bx = expr1[1];
01788 const Expr& ax = expr2[0];
01789 const Expr& alpha = expr2[1];
01790 Rational a = isMult(ax)? ax[0].getRational() : 1;
01791 Rational b = isMult(bx)? bx[0].getRational() : 1;
01792 const Expr& x = isMult(ax)? ax[1] : ax;
01793
01794 if(CHECK_PROOFS) {
01795
01796 CHECK_SOUND(isIntPred(isIntAlphaExpr) && isIntAlphaExpr[0] == alpha,
01797 "ArithTheoremProducer::darkGrayShadow2ab:\n "
01798 "wrong integrality constraint:\n alpha = "
01799 +alpha.toString()+"\n isIntAlpha = "
01800 +isIntAlphaExpr.toString());
01801 CHECK_SOUND(isIntPred(isIntBetaExpr) && isIntBetaExpr[0] == beta,
01802 "ArithTheoremProducer::darkGrayShadow2ab:\n "
01803 "wrong integrality constraint:\n beta = "
01804 +beta.toString()+"\n isIntBeta = "
01805 +isIntBetaExpr.toString());
01806 CHECK_SOUND(isIntPred(isIntxExpr) && isIntxExpr[0] == x,
01807 "ArithTheoremProducer::darkGrayShadow2ab:\n "
01808 "wrong integrality constraint:\n x = "
01809 +x.toString()+"\n isIntx = "
01810 +isIntxExpr.toString());
01811
01812 CHECK_SOUND(!isMult(ax) || ax.arity() == 2,
01813 "ArithTheoremProducer::darkGrayShadow2ba:\n ax<=alpha: " +
01814 axLEalpha.toString());
01815 CHECK_SOUND(!isMult(bx) || (bx.arity() == 2 && bx[1] == x),
01816 "ArithTheoremProducer::darkGrayShadow2ba:\n beta<=bx: "
01817 +betaLEbx.toString()
01818 +"\n ax<=alpha: "+ axLEalpha.toString());
01819 CHECK_SOUND(1 <= b && b <= a && 2 <= a,
01820 "ArithTheoremProducer::darkGrayShadow2ba:\n beta<=bx: "
01821 +betaLEbx.toString()
01822 +"\n ax<=alpha: "+ axLEalpha.toString());
01823 }
01824 vector<Theorem> thms;
01825 thms.push_back(betaLEbx);
01826 thms.push_back(axLEalpha);
01827 thms.push_back(isIntAlpha);
01828 thms.push_back(isIntBeta);
01829 thms.push_back(isIntx);
01830 Assumptions A(thms);
01831 Proof pf;
01832 if(withProof()) {
01833 vector<Proof> pfs;
01834 pfs.push_back(betaLEbx.getProof());
01835 pfs.push_back(axLEalpha.getProof());
01836 pfs.push_back(isIntAlpha.getProof());
01837 pfs.push_back(isIntBeta.getProof());
01838 pfs.push_back(isIntx.getProof());
01839
01840 pf = newPf("dark_grayshadow_2ba", betaLEbx.getExpr(),
01841 axLEalpha.getExpr(), pfs);
01842 }
01843
01844 Expr bAlpha = multExpr(rat(b), alpha);
01845 Expr aBeta = multExpr(rat(a), beta);
01846 Expr t = minusExpr(bAlpha, aBeta);
01847 Expr d = darkShadow(rat(a*b-1), t);
01848 Expr g = grayShadow(bx, beta, 0, b-1);
01849 return newTheorem((d || g) && (!d || !g), A, pf);
01850 }
01851
01852
01853
01854 Theorem ArithTheoremProducer::expandDarkShadow(const Theorem& darkShadow) {
01855 const Expr& theShadow = darkShadow.getExpr();
01856 if(CHECK_PROOFS){
01857 CHECK_SOUND(isDarkShadow(theShadow),
01858 "ArithTheoremProducer::expandDarkShadow: not DARK_SHADOW: " +
01859 theShadow.toString());
01860 }
01861 Proof pf;
01862 if(withProof())
01863 pf = newPf("expand_dark_shadow", theShadow, darkShadow.getProof());
01864 return newTheorem(leExpr(theShadow[0], theShadow[1]), darkShadow.getAssumptionsRef(), pf);
01865 }
01866
01867
01868
01869 Theorem ArithTheoremProducer::expandGrayShadow0(const Theorem& grayShadow) {
01870 const Expr& theShadow = grayShadow.getExpr();
01871 if(CHECK_PROOFS) {
01872 CHECK_SOUND(isGrayShadow(theShadow),
01873 "ArithTheoremProducer::expandGrayShadowConst0:"
01874 " not GRAY_SHADOW: " +
01875 theShadow.toString());
01876 CHECK_SOUND(theShadow[2] == theShadow[3],
01877 "ArithTheoremProducer::expandGrayShadow0: c1!=c2: " +
01878 theShadow.toString());
01879 }
01880 Proof pf;
01881 if(withProof()) pf = newPf("expand_gray_shadowconst0", theShadow,
01882 grayShadow.getProof());
01883 const Expr& v = theShadow[0];
01884 const Expr& e = theShadow[1];
01885 return newRWTheorem(v, e + theShadow[2], grayShadow.getAssumptionsRef(), pf);
01886 }
01887
01888
01889
01890
01891
01892
01893
01894 Theorem ArithTheoremProducer::splitGrayShadow(const Theorem& gThm) {
01895 const Expr& theShadow = gThm.getExpr();
01896 if(CHECK_PROOFS) {
01897 CHECK_SOUND(isGrayShadow(theShadow),
01898 "ArithTheoremProducer::expandGrayShadowConst: not a shadow" +
01899 theShadow.toString());
01900 }
01901
01902 const Rational& c1 = theShadow[2].getRational();
01903 const Rational& c2 = theShadow[3].getRational();
01904
01905 if(CHECK_PROOFS) {
01906 CHECK_SOUND(c1.isInteger() && c2.isInteger() && c1 < c2,
01907 "ArithTheoremProducer::expandGrayShadow: " +
01908 theShadow.toString());
01909 }
01910
01911 const Expr& v = theShadow[0];
01912 const Expr& e = theShadow[1];
01913
01914 Proof pf;
01915 Rational c(floor((c1+c2) / 2));
01916 Expr g1(grayShadow(v, e, c1, c));
01917 Expr g2(grayShadow(v, e, c+1, c2));
01918
01919 if(withProof()){
01920 vector<Expr> exprs;
01921 exprs.push_back(theShadow);
01922 exprs.push_back(g1);
01923 exprs.push_back(g2);
01924 pf = newPf("split_gray_shadow", exprs, gThm.getProof());
01925 }
01926
01927 return newTheorem((g1 || g2) && (!g1 || !g2), gThm.getAssumptionsRef(), pf);
01928 }
01929
01930
01931 Theorem ArithTheoremProducer::expandGrayShadow(const Theorem& gThm) {
01932 const Expr& theShadow = gThm.getExpr();
01933 if(CHECK_PROOFS) {
01934 CHECK_SOUND(isGrayShadow(theShadow),
01935 "ArithTheoremProducer::expandGrayShadowConst: not a shadow" +
01936 theShadow.toString());
01937 }
01938
01939 const Rational& c1 = theShadow[2].getRational();
01940 const Rational& c2 = theShadow[3].getRational();
01941
01942 if(CHECK_PROOFS) {
01943 CHECK_SOUND(c1.isInteger() && c2.isInteger() && c1 < c2,
01944 "ArithTheoremProducer::expandGrayShadow: " +
01945 theShadow.toString());
01946 }
01947
01948 const Expr& v = theShadow[0];
01949 const Expr& e = theShadow[1];
01950
01951 Proof pf;
01952 if(withProof())
01953 pf = newPf("expand_gray_shadow", theShadow, gThm.getProof());
01954 Expr ineq1(leExpr(e+rat(c1), v));
01955 Expr ineq2(leExpr(v, e+rat(c2)));
01956 return newTheorem(ineq1 && ineq2, gThm.getAssumptionsRef(), pf);
01957 }
01958
01959
01960
01961 Theorem
01962 ArithTheoremProducer::expandGrayShadowConst(const Theorem& gThm) {
01963 const Expr& theShadow = gThm.getExpr();
01964 const Expr& ax = theShadow[0];
01965 const Expr& cExpr = theShadow[1];
01966 const Expr& bExpr = theShadow[2];
01967
01968 if(CHECK_PROOFS) {
01969 CHECK_SOUND(!isMult(ax) || ax[0].isRational(),
01970 "ArithTheoremProducer::expandGrayShadowConst: "
01971 "'a' in a*x is not a const: " +theShadow.toString());
01972 }
01973
01974 Rational a = isMult(ax)? ax[0].getRational() : 1;
01975
01976 if(CHECK_PROOFS) {
01977 CHECK_SOUND(isGrayShadow(theShadow),
01978 "ArithTheoremProducer::expandGrayShadowConst: "
01979 "not a GRAY_SHADOW: " +theShadow.toString());
01980 CHECK_SOUND(a.isInteger() && a >= 1,
01981 "ArithTheoremProducer::expandGrayShadowConst: "
01982 "'a' is not integer: " +theShadow.toString());
01983 CHECK_SOUND(cExpr.isRational(),
01984 "ArithTheoremProducer::expandGrayShadowConst: "
01985 "'c' is not rational" +theShadow.toString());
01986 CHECK_SOUND(bExpr.isRational() && bExpr.getRational().isInteger(),
01987 "ArithTheoremProducer::expandGrayShadowConst: b not integer: "
01988 +theShadow.toString());
01989 }
01990
01991 const Rational& b = bExpr.getRational();
01992 const Rational& c = cExpr.getRational();
01993 Rational j = constRHSGrayShadow(c,b,a);
01994
01995 Rational signB = (b>0)? 1 : -1;
01996
01997 Rational bAbs = abs(b);
01998
01999 const Assumptions& assump(gThm.getAssumptionsRef());
02000 Proof pf;
02001 Theorem conc;
02002
02003 if(bAbs < j) {
02004 if(withProof())
02005 pf = newPf("expand_gray_shadow_const_0", theShadow,
02006 gThm.getProof());
02007 conc = newTheorem(d_em->falseExpr(), assump, pf);
02008 } else if(bAbs < a+j) {
02009 if(withProof())
02010 pf = newPf("expand_gray_shadow_const_1", theShadow,
02011 gThm.getProof());
02012 conc = newRWTheorem(ax, rat(c+b-signB*j), assump, pf);
02013 } else {
02014 if(withProof())
02015 pf = newPf("expand_gray_shadow_const", theShadow,
02016 gThm.getProof());
02017 Expr newGrayShadow(Expr(GRAY_SHADOW, ax, cExpr, rat(b-signB*(a+j))));
02018 conc = newTheorem(ax.eqExpr(rat(c+b-signB*j)).orExpr(newGrayShadow),
02019 assump, pf);
02020 }
02021
02022 return conc;
02023 }
02024
02025
02026 Theorem
02027 ArithTheoremProducer::grayShadowConst(const Theorem& gThm) {
02028 const Expr& g = gThm.getExpr();
02029 bool checkProofs(CHECK_PROOFS);
02030 if(checkProofs) {
02031 CHECK_SOUND(isGrayShadow(g), "ArithTheoremProducer::grayShadowConst("
02032 +g.toString()+")");
02033 }
02034
02035 const Expr& ax = g[0];
02036 const Expr& e = g[1];
02037 const Rational& c1 = g[2].getRational();
02038 const Rational& c2 = g[3].getRational();
02039 Expr aExpr, x;
02040 d_theoryArith->separateMonomial(ax, aExpr, x);
02041
02042 if(checkProofs) {
02043 CHECK_SOUND(e.isRational() && e.getRational().isInteger(),
02044 "ArithTheoremProducer::grayShadowConst("+g.toString()+")");
02045 CHECK_SOUND(aExpr.isRational(),
02046 "ArithTheoremProducer::grayShadowConst("+g.toString()+")");
02047 }
02048
02049 const Rational& a = aExpr.getRational();
02050 const Rational& c = e.getRational();
02051
02052 if(checkProofs) {
02053 CHECK_SOUND(a.isInteger() && a >= 2,
02054 "ArithTheoremProducer::grayShadowConst("+g.toString()+")");
02055 }
02056
02057 Rational newC1 = ceil((c1+c)/a), newC2 = floor((c2+c)/a);
02058 Expr newG((newC1 > newC2)? d_em->falseExpr()
02059 : grayShadow(x, rat(0), newC1, newC2));
02060 Proof pf;
02061 if(withProof())
02062 pf = newPf("gray_shadow_const", g, newG, gThm.getProof());
02063 return newTheorem(newG, gThm.getAssumptionsRef(), pf);
02064 }
02065
02066
02067 Rational ArithTheoremProducer::constRHSGrayShadow(const Rational& c,
02068 const Rational& b,
02069 const Rational& a) {
02070 DebugAssert(c.isInteger() &&
02071 b.isInteger() &&
02072 a.isInteger() &&
02073 b != 0,
02074 "ArithTheoremProducer::constRHSGrayShadow: a, b, c must be ints");
02075 if (b > 0)
02076 return mod(c+b, a);
02077 else
02078 return mod(a-(c+b), a);
02079 }
02080
02081
02082
02083
02084
02085 Theorem ArithTheoremProducer::lessThanToLE(const Theorem& less,
02086 const Theorem& isIntLHS,
02087 const Theorem& isIntRHS,
02088 bool changeRight) {
02089 const Expr& ineq = less.getExpr();
02090 const Expr& isIntLHSexpr = isIntLHS.getExpr();
02091 const Expr& isIntRHSexpr = isIntRHS.getExpr();
02092
02093 if(CHECK_PROOFS) {
02094 CHECK_SOUND(isLT(ineq),
02095 "ArithTheoremProducer::LTtoLE: ineq must be <");
02096
02097 CHECK_SOUND(isIntPred(isIntLHSexpr) && isIntLHSexpr[0] == ineq[0],
02098 "ArithTheoremProducer::lessThanToLE: bad integrality check:\n"
02099 " ineq = "+ineq.toString()+"\n isIntLHS = "
02100 +isIntLHSexpr.toString());
02101 CHECK_SOUND(isIntPred(isIntRHSexpr) && isIntRHSexpr[0] == ineq[1],
02102 "ArithTheoremProducer::lessThanToLE: bad integrality check:\n"
02103 " ineq = "+ineq.toString()+"\n isIntRHS = "
02104 +isIntRHSexpr.toString());
02105 }
02106 vector<Theorem> thms;
02107 thms.push_back(less);
02108 thms.push_back(isIntLHS);
02109 thms.push_back(isIntRHS);
02110 Assumptions a(thms);
02111 Proof pf;
02112 Expr le = changeRight?
02113 leExpr(ineq[0], ineq[1] + rat(-1))
02114 : leExpr(ineq[0] + rat(1), ineq[1]);
02115
02116 if(withProof()) {
02117 vector<Proof> pfs;
02118 pfs.push_back(less.getProof());
02119 pfs.push_back(isIntLHS.getProof());
02120 pfs.push_back(isIntRHS.getProof());
02121 pf = newPf(changeRight? "lessThan_To_LE_rhs" : "lessThan_To_LE_lhs",
02122 ineq, le, pfs);
02123 }
02124
02125 return newRWTheorem(ineq, le, a, pf);
02126 }
02127
02128
02129
02130
02131
02132
02133
02134
02135
02136
02137 Theorem
02138 ArithTheoremProducer::intVarEqnConst(const Expr& eqn,
02139 const Theorem& isIntx) {
02140 const Expr& left(eqn[0]);
02141 const Expr& right(eqn[1]);
02142 const Expr& isIntxexpr(isIntx.getExpr());
02143
02144 if(CHECK_PROOFS) {
02145 CHECK_SOUND((isMult(right) && right[0].isRational())
02146 || (right.arity() == 2 && isPlus(right)
02147 && right[0].isRational()
02148 && ((!isMult(right[1]) || right[1][0].isRational()))),
02149 "ArithTheoremProducer::intVarEqnConst: "
02150 "rhs has a wrong format: " + right.toString());
02151 CHECK_SOUND(left.isRational() && 0 == left.getRational(),
02152 "ArithTheoremProducer:intVarEqnConst:left is not a zero: " +
02153 left.toString());
02154 }
02155
02156 Expr x(right);
02157 Rational a(1), c(0);
02158 if(isMult(right)) {
02159 Expr aExpr;
02160 d_theoryArith->separateMonomial(right, aExpr, x);
02161 a = aExpr.getRational();
02162 } else {
02163 c = right[0].getRational();
02164 Expr aExpr;
02165 d_theoryArith->separateMonomial(right[1], aExpr, x);
02166 a = aExpr.getRational();
02167 }
02168 if(CHECK_PROOFS) {
02169 CHECK_SOUND(isIntPred(isIntxexpr) && isIntxexpr[0] == x,
02170 "ArithTheoremProducer:intVarEqnConst: "
02171 "bad integrality constraint:\n right = " +
02172 right.toString()+"\n isIntx = "+isIntxexpr.toString());
02173 CHECK_SOUND(a!=0, "ArithTheoremProducer:intVarEqnConst: eqn = "
02174 +eqn.toString());
02175 }
02176 const Assumptions& assump(isIntx.getAssumptionsRef());
02177 Proof pf;
02178 if(withProof())
02179 pf = newPf("int_const_eq", eqn, isIntx.getProof());
02180
02181
02182 Rational r(-c/a);
02183
02184 if(r.isInteger())
02185 return newRWTheorem(eqn, x.eqExpr(rat(r)), assump, pf);
02186 else
02187 return newRWTheorem(eqn, d_em->falseExpr(), assump, pf);
02188 }
02189
02190
02191 Expr
02192 ArithTheoremProducer::create_t(const Expr& eqn) {
02193 const Expr& lhs = eqn[0];
02194 DebugAssert(isMult(lhs),
02195 CLASS_NAME "create_t : lhs must be a MULT"
02196 + lhs.toString());
02197 const Expr& x = lhs[1];
02198 Rational m = lhs[0].getRational()+1;
02199 DebugAssert(m > 0, "ArithTheoremProducer::create_t: m = "+m.toString());
02200 vector<Expr> kids;
02201 if(isPlus(eqn[1]))
02202 sumModM(kids, eqn[1], m, m);
02203 else
02204 kids.push_back(monomialModM(eqn[1], m, m));
02205
02206 kids.push_back(multExpr(rat(1/m), x));
02207 return plusExpr(kids);
02208 }
02209
02210 Expr
02211 ArithTheoremProducer::create_t2(const Expr& lhs, const Expr& rhs,
02212 const Expr& sigma) {
02213 Rational m = lhs[0].getRational()+1;
02214 DebugAssert(m > 0, "ArithTheoremProducer::create_t2: m = "+m.toString());
02215 vector<Expr> kids;
02216 if(isPlus(rhs))
02217 sumModM(kids, rhs, m, -1);
02218 else {
02219 kids.push_back(rat(0));
02220 Expr monom = monomialModM(rhs, m, -1);
02221 if(!monom.isRational())
02222 kids.push_back(monom);
02223 else
02224 DebugAssert(monom.getRational() == 0, "");
02225 }
02226 kids.push_back(rat(m)*sigma);
02227 return plusExpr(kids);
02228 }
02229
02230 Expr
02231 ArithTheoremProducer::create_t3(const Expr& lhs, const Expr& rhs,
02232 const Expr& sigma) {
02233 const Rational& a = lhs[0].getRational();
02234 Rational m = a+1;
02235 DebugAssert(m > 0, "ArithTheoremProducer::create_t3: m = "+m.toString());
02236 vector<Expr> kids;
02237 if(isPlus(rhs))
02238 sumMulF(kids, rhs, m, 1);
02239 else {
02240 kids.push_back(rat(0));
02241 Expr monom = monomialMulF(rhs, m, 1);
02242 if(!monom.isRational())
02243 kids.push_back(monom);
02244 else
02245 DebugAssert(monom.getRational() == 0, "");
02246 }
02247 kids.push_back(rat(-a)*sigma);
02248 return plusExpr(kids);
02249 }
02250
02251 Rational
02252 ArithTheoremProducer::modEq(const Rational& i, const Rational& m) {
02253 DebugAssert(m > 0, "ArithTheoremProducer::modEq: m = "+m.toString());
02254 Rational half(1,2);
02255 Rational res((i - m*(floor((i/m) + half))));
02256 TRACE("arith eq", "modEq("+i.toString()+", "+m.toString()+") = ", res, "");
02257 return res;
02258 }
02259
02260 Rational
02261 ArithTheoremProducer::f(const Rational& i, const Rational& m) {
02262 DebugAssert(m > 0, "ArithTheoremProducer::f: m = "+m.toString());
02263 Rational half(1,2);
02264 return (floor(i/m + half)+modEq(i,m));
02265 }
02266
02267 void
02268 ArithTheoremProducer::sumModM(vector<Expr>& summands, const Expr& sum,
02269 const Rational& m, const Rational& divisor) {
02270 DebugAssert(divisor != 0, "ArithTheoremProducer::sumModM: divisor = "
02271 +divisor.toString());
02272 Expr::iterator i = sum.begin();
02273 DebugAssert(i != sum.end(), CLASS_NAME "::sumModM");
02274 Rational C = i->getRational();
02275 C = modEq(C,m)/divisor;
02276 summands.push_back(rat(C));
02277 i++;
02278 for(Expr::iterator iend=sum.end(); i!=iend; ++i) {
02279 Expr monom = monomialModM(*i, m, divisor);
02280 if(!monom.isRational())
02281 summands.push_back(monom);
02282 else
02283 DebugAssert(monom.getRational() == 0, "");
02284 }
02285 }
02286
02287 Expr
02288 ArithTheoremProducer::monomialModM(const Expr& i,
02289 const Rational& m, const Rational& divisor)
02290 {
02291 DebugAssert(divisor != 0, "ArithTheoremProducer::monomialModM: divisor = "
02292 +divisor.toString());
02293 Expr res;
02294 if(isMult(i)) {
02295 Rational ai = i[0].getRational();
02296 ai = modEq(ai,m)/divisor;
02297 if(0 == ai) res = rat(0);
02298 else if(1 == ai && i.arity() == 2) res = i[1];
02299 else {
02300 vector<Expr> kids = i.getKids();
02301 kids[0] = rat(ai);
02302 res = multExpr(kids);
02303 }
02304 } else {
02305 Rational ai = modEq(1,m)/divisor;
02306 if(1 == ai) res = i;
02307 else res = rat(ai)*i;
02308 }
02309 DebugAssert(!res.isNull(), "ArithTheoremProducer::monomialModM()");
02310 TRACE("arith eq", "monomialModM(i="+i.toString()+", m="+m.toString()
02311 +", div="+divisor.toString()+") = ", res, "");
02312 return res;
02313 }
02314
02315 void
02316 ArithTheoremProducer::sumMulF(vector<Expr>& summands, const Expr& sum,
02317 const Rational& m, const Rational& divisor) {
02318 DebugAssert(divisor != 0, "ArithTheoremProducer::sumMulF: divisor = "
02319 +divisor.toString());
02320 Expr::iterator i = sum.begin();
02321 DebugAssert(i != sum.end(), CLASS_NAME "::sumModM");
02322 Rational C = i->getRational();
02323 C = f(C,m)/divisor;
02324 summands.push_back(rat(C));
02325 i++;
02326 for(Expr::iterator iend=sum.end(); i!=iend; ++i) {
02327 Expr monom = monomialMulF(*i, m, divisor);
02328 if(!monom.isRational())
02329 summands.push_back(monom);
02330 else
02331 DebugAssert(monom.getRational() == 0, "");
02332 }
02333 }
02334
02335 Expr
02336 ArithTheoremProducer::monomialMulF(const Expr& i,
02337 const Rational& m, const Rational& divisor)
02338 {
02339 DebugAssert(divisor != 0, "ArithTheoremProducer::monomialMulF: divisor = "
02340 +divisor.toString());
02341 Rational ai = isMult(i) ? (i)[0].getRational() : 1;
02342 Expr xi = isMult(i) ? (i)[1] : (i);
02343 ai = f(ai,m)/divisor;
02344 if(0 == ai) return rat(0);
02345 if(1 == ai) return xi;
02346 return multExpr(rat(ai), xi);
02347 }
02348
02349
02350
02351
02352 Expr
02353 ArithTheoremProducer::substitute(const Expr& term, ExprMap<Expr>& eMap)
02354 {
02355 ExprMap<Expr>::iterator i, iend = eMap.end();
02356
02357 i = eMap.find(term);
02358 if(iend != i)
02359 return (*i).second;
02360
02361 if (isMult(term)) {
02362
02363 i = eMap.find(term[1]);
02364 if(iend != i)
02365 return term[0]*(*i).second;
02366 else
02367 return term;
02368 }
02369
02370 if(isPlus(term)) {
02371 vector<Expr> output;
02372 for(Expr::iterator j = term.begin(), jend = term.end(); j != jend; ++j)
02373 output.push_back(substitute(*j, eMap));
02374 return plusExpr(output);
02375 }
02376 return term;
02377 }
02378
02379 bool ArithTheoremProducer::greaterthan(const Expr & l, const Expr & r)
02380 {
02381
02382 if (l==r) return false;
02383
02384 switch(l.getKind()) {
02385 case RATIONAL_EXPR:
02386 DebugAssert(!r.isRational(), "");
02387 return true;
02388 break;
02389 case POW:
02390 switch (r.getKind()) {
02391 case RATIONAL_EXPR:
02392
02393
02394 return false;
02395 break;
02396 case POW:
02397
02398
02399 return
02400 ((r[1] < l[1]) ||
02401 ((r[1]==l[1]) && (r[0].getRational() < l[0].getRational())));
02402 break;
02403
02404 case MULT:
02405 DebugAssert(r.arity() > 1, "");
02406 DebugAssert((r.arity() > 2) || (r[1] != l), "");
02407 if (r[1] == l) return false;
02408 return greaterthan(l, r[1]);
02409 break;
02410 case PLUS:
02411 DebugAssert(false, "");
02412 return true;
02413 break;
02414 default:
02415
02416 return ((r < l[1]) || ((r == l[1]) && l[0].getRational() > 1));
02417 break;
02418 }
02419 break;
02420 case MULT:
02421 DebugAssert(l.arity() > 1, "");
02422 switch (r.getKind()) {
02423 case RATIONAL_EXPR:
02424 return false;
02425 break;
02426 case POW:
02427 DebugAssert(l.arity() > 1, "");
02428 DebugAssert((l.arity() > 2) || (l[1] != r), "");
02429
02430
02431 return ((l[1] == r) || greaterthan(l[1], r));
02432 break;
02433 case MULT:
02434 {
02435
02436 DebugAssert(r.arity() > 1, "");
02437 Expr::iterator i = l.begin();
02438 Expr::iterator j = r.begin();
02439 ++i;
02440 ++j;
02441 for (; i != l.end() && j != r.end(); ++i, ++j) {
02442 if (*i == *j)
02443 continue;
02444 return greaterthan(*i,*j);
02445 }
02446 DebugAssert(i != l.end() || j != r.end(), "");
02447 if (i == l.end()) {
02448
02449 return false;
02450 }
02451 else
02452 {
02453
02454 return true;
02455 }
02456 }
02457 break;
02458 case PLUS:
02459 DebugAssert(false, "");
02460 return true;
02461 break;
02462 default:
02463
02464 DebugAssert((l.arity() > 2) || (l[1] != r), "");
02465 return ((l[1] == r) || greaterthan(l[1], r));
02466 break;
02467 }
02468 break;
02469 case PLUS:
02470 DebugAssert(false, "");
02471 return true;
02472 break;
02473 default:
02474
02475 switch (r.getKind()) {
02476 case RATIONAL_EXPR:
02477 return false;
02478 break;
02479 case POW:
02480 return ((r[1] < l) || ((r[1] == l) && (r[0].getRational() < 1)));
02481 break;
02482 case MULT:
02483 DebugAssert(r.arity() > 1, "");
02484 DebugAssert((r.arity() > 2) || (r[1] != l), "");
02485 if (l == r[1]) return false;
02486 return greaterthan(l,r[1]);
02487 break;
02488 case PLUS:
02489 DebugAssert(false, "");
02490 return true;
02491 break;
02492 default:
02493
02494 return (r < l);
02495 break;
02496 }
02497 break;
02498 }
02499 }
02500
02501
02502
02503
02504
02505 Theorem ArithTheoremProducer::IsIntegerElim(const Theorem& isIntx)
02506 {
02507 Expr expr = isIntx.getExpr();
02508 if (CHECK_PROOFS) {
02509 CHECK_SOUND(expr.getKind() == IS_INTEGER,
02510 "Expected IS_INTEGER predicate");
02511 }
02512 expr = expr[0];
02513 DebugAssert(!d_theoryArith->isInteger(expr), "Expected non-integer");
02514
02515 Assumptions a(isIntx);
02516 Proof pf;
02517
02518 if (withProof())
02519 {
02520 pf = newPf("isIntElim", isIntx.getProof());
02521 }
02522
02523 Expr newVar = d_em->newBoundVarExpr(d_theoryArith->intType());
02524 Expr res = d_em->newClosureExpr(EXISTS, newVar, newVar.eqExpr(expr));
02525
02526 return newTheorem(res, a, pf);
02527 }
02528
02529
02530 Theorem
02531 ArithTheoremProducer::eqElimIntRule(const Theorem& eqn, const Theorem& isIntx,
02532 const vector<Theorem>& isIntVars) {
02533 TRACE("arith eq", "eqElimIntRule(", eqn.getExpr(), ") {");
02534 Proof pf;
02535
02536 if(CHECK_PROOFS)
02537 CHECK_SOUND(eqn.isRewrite(),
02538 "ArithTheoremProducer::eqElimInt: input must be an equation" +
02539 eqn.toString());
02540
02541 const Expr& lhs = eqn.getLHS();
02542 const Expr& rhs = eqn.getRHS();
02543 Expr a, x;
02544 d_theoryArith->separateMonomial(lhs, a, x);
02545
02546 if(CHECK_PROOFS) {
02547
02548 const Expr& isIntxe = isIntx.getExpr();
02549 CHECK_SOUND(isIntPred(isIntxe) && isIntxe[0] == x,
02550 "ArithTheoremProducer::eqElimInt\n eqn = "
02551 +eqn.getExpr().toString()
02552 +"\n isIntx = "+isIntxe.toString());
02553 CHECK_SOUND(isRational(a) && a.getRational().isInteger()
02554 && a.getRational() >= 2,
02555 "ArithTheoremProducer::eqElimInt:\n lhs = "+lhs.toString());
02556
02557
02558 CHECK_SOUND(!isDivide(rhs),
02559 "ArithTheoremProducer::eqElimInt:\n rhs = "+rhs.toString());
02560
02561 if(!isPlus(rhs)) {
02562 Expr c, v;
02563 d_theoryArith->separateMonomial(rhs, c, v);
02564 CHECK_SOUND(isIntVars.size() == 1
02565 && isIntPred(isIntVars[0].getExpr())
02566 && isIntVars[0].getExpr()[0] == v
02567 && isRational(c) && c.getRational().isInteger(),
02568 "ArithTheoremProducer::eqElimInt:\n rhs = "+rhs.toString()
02569 +"isIntVars.size = "+int2string(isIntVars.size()));
02570 } else {
02571 CHECK_SOUND(isIntVars.size() + 1 == (size_t)rhs.arity(),
02572 "ArithTheoremProducer::eqElimInt: rhs = "+rhs.toString());
02573
02574 CHECK_SOUND(isRational(rhs[0]) && rhs[0].getRational().isInteger(),
02575 "ArithTheoremProducer::eqElimInt: rhs = "+rhs.toString());
02576
02577 for(size_t i=0, iend=isIntVars.size(); i<iend; ++i) {
02578 Expr c, v;
02579 d_theoryArith->separateMonomial(rhs[i+1], c, v);
02580 const Expr& isInt(isIntVars[i].getExpr());
02581 CHECK_SOUND(isIntPred(isInt) && isInt[0] == v
02582 && isRational(c) && c.getRational().isInteger(),
02583 "ArithTheoremProducer::eqElimInt:\n rhs["+int2string(i+1)
02584 +"] = "+rhs[i+1].toString()
02585 +"\n isInt = "+isInt.toString());
02586 }
02587 }
02588 }
02589
02590
02591 static int varCount(0);
02592 Expr newVar = d_em->newBoundVarExpr("_int_var", int2string(varCount++));
02593 newVar.setType(intType());
02594 Expr t2 = create_t2(lhs, rhs, newVar);
02595 Expr t3 = create_t3(lhs, rhs, newVar);
02596 vector<Expr> vars;
02597 vars.push_back(newVar);
02598 Expr res = d_em->newClosureExpr(EXISTS, vars,
02599 x.eqExpr(t2) && rat(0).eqExpr(t3));
02600
02601 vector<Theorem> thms(isIntVars);
02602 thms.push_back(isIntx);
02603 thms.push_back(eqn);
02604 Assumptions assump(thms);
02605
02606 if(withProof()) {
02607 vector<Proof> pfs;
02608 pfs.push_back(eqn.getProof());
02609 pfs.push_back(isIntx.getProof());
02610 vector<Theorem>::const_iterator i=isIntVars.begin(), iend=isIntVars.end();
02611 for(; i!=iend; ++i)
02612 pfs.push_back(i->getProof());
02613 pf = newPf("eq_elim_int", eqn.getExpr(), res , pfs);
02614 }
02615
02616 Theorem thm(newTheorem(res, assump, pf));
02617 TRACE("arith eq", "eqElimIntRule => ", thm.getExpr(), " }");
02618 return thm;
02619 }
02620
02621
02622 Theorem
02623 ArithTheoremProducer::isIntConst(const Expr& e) {
02624 Proof pf;
02625
02626 if(CHECK_PROOFS) {
02627 CHECK_SOUND(isIntPred(e) && e[0].isRational(),
02628 "ArithTheoremProducer::isIntConst(e = "
02629 +e.toString()+")");
02630 }
02631 if(withProof())
02632 pf = newPf("is_int_const", e);
02633 bool isInt = e[0].getRational().isInteger();
02634 return newRWTheorem(e, isInt? d_em->trueExpr() : d_em->falseExpr(), Assumptions::emptyAssump(), pf);
02635 }
02636
02637
02638 Theorem
02639 ArithTheoremProducer::equalLeaves1(const Theorem& thm)
02640 {
02641 Proof pf;
02642 const Expr& e = thm.getRHS();
02643
02644 if (CHECK_PROOFS) {
02645 CHECK_SOUND(e[1].getKind() == RATIONAL_EXPR &&
02646 e[1].getRational() == Rational(0) &&
02647 e[0].getKind() == PLUS &&
02648 e[0].arity() == 3 &&
02649 e[0][0].getKind() == RATIONAL_EXPR &&
02650 e[0][0].getRational() == Rational(0) &&
02651 e[0][1].getKind() == MULT &&
02652 e[0][1].arity() == 2 &&
02653 e[0][1][0].getKind() == RATIONAL_EXPR &&
02654 e[0][1][0].getRational() == Rational(-1),
02655 "equalLeaves1");
02656 }
02657 if (withProof())
02658 {
02659 vector<Proof> pfs;
02660 pfs.push_back(thm.getProof());
02661 pf = newPf("equalLeaves1", e, pfs);
02662 }
02663 return newRWTheorem(e, e[0][1][1].eqExpr(e[0][2]), thm.getAssumptionsRef(), pf);
02664 }
02665
02666
02667 Theorem
02668 ArithTheoremProducer::equalLeaves2(const Theorem& thm)
02669 {
02670 Proof pf;
02671 const Expr& e = thm.getRHS();
02672
02673 if (CHECK_PROOFS) {
02674 CHECK_SOUND(e[0].getKind() == RATIONAL_EXPR &&
02675 e[0].getRational() == Rational(0) &&
02676 e[1].getKind() == PLUS &&
02677 e[1].arity() == 3 &&
02678 e[1][0].getKind() == RATIONAL_EXPR &&
02679 e[1][0].getRational() == Rational(0) &&
02680 e[1][1].getKind() == MULT &&
02681 e[1][1].arity() == 2 &&
02682 e[1][1][0].getKind() == RATIONAL_EXPR &&
02683 e[1][1][0].getRational() == Rational(-1),
02684 "equalLeaves2");
02685 }
02686 if (withProof())
02687 {
02688 vector<Proof> pfs;
02689 pfs.push_back(thm.getProof());
02690 pf = newPf("equalLeaves2", e, pfs);
02691 }
02692 return newRWTheorem(e, e[1][1][1].eqExpr(e[1][2]), thm.getAssumptionsRef(), pf);
02693 }
02694
02695
02696 Theorem
02697 ArithTheoremProducer::equalLeaves3(const Theorem& thm)
02698 {
02699 Proof pf;
02700 const Expr& e = thm.getRHS();
02701
02702 if (CHECK_PROOFS) {
02703 CHECK_SOUND(e[1].getKind() == RATIONAL_EXPR &&
02704 e[1].getRational() == Rational(0) &&
02705 e[0].getKind() == PLUS &&
02706 e[0].arity() == 3 &&
02707 e[0][0].getKind() == RATIONAL_EXPR &&
02708 e[0][0].getRational() == Rational(0) &&
02709 e[0][2].getKind() == MULT &&
02710 e[0][2].arity() == 2 &&
02711 e[0][2][0].getKind() == RATIONAL_EXPR &&
02712 e[0][2][0].getRational() == Rational(-1),
02713 "equalLeaves3");
02714 }
02715 if (withProof())
02716 {
02717 vector<Proof> pfs;
02718 pfs.push_back(thm.getProof());
02719 pf = newPf("equalLeaves3", e, pfs);
02720 }
02721 return newRWTheorem(e, e[0][2][1].eqExpr(e[0][1]), thm.getAssumptionsRef(), pf);
02722 }
02723
02724
02725 Theorem
02726 ArithTheoremProducer::equalLeaves4(const Theorem& thm)
02727 {
02728 Proof pf;
02729 const Expr& e = thm.getRHS();
02730
02731 if (CHECK_PROOFS) {
02732 CHECK_SOUND(e[0].getKind() == RATIONAL_EXPR &&
02733 e[0].getRational() == Rational(0) &&
02734 e[1].getKind() == PLUS &&
02735 e[1].arity() == 3 &&
02736 e[1][0].getKind() == RATIONAL_EXPR &&
02737 e[1][0].getRational() == Rational(0) &&
02738 e[1][2].getKind() == MULT &&
02739 e[1][2].arity() == 2 &&
02740 e[1][2][0].getKind() == RATIONAL_EXPR &&
02741 e[1][2][0].getRational() == Rational(-1),
02742 "equalLeaves4");
02743 }
02744 if (withProof())
02745 {
02746 vector<Proof> pfs;
02747 pfs.push_back(thm.getProof());
02748 pf = newPf("equalLeaves4", e, pfs);
02749 }
02750 return newRWTheorem(e, e[1][2][1].eqExpr(e[1][1]), thm.getAssumptionsRef(), pf);
02751 }
02752
02753 Theorem
02754 ArithTheoremProducer::diseqToIneq(const Theorem& diseq) {
02755 Proof pf;
02756
02757 const Expr& e = diseq.getExpr();
02758
02759 if(CHECK_PROOFS) {
02760 CHECK_SOUND(e.isNot() && e[0].isEq(),
02761 "ArithTheoremProducer::diseqToIneq: expected disequality:\n"
02762 " e = "+e.toString());
02763 }
02764
02765 const Expr& x = e[0][0];
02766 const Expr& y = e[0][1];
02767
02768 if(withProof())
02769 pf = newPf(e, diseq.getProof());
02770 return newTheorem(ltExpr(x,y).orExpr(gtExpr(x,y)), diseq.getAssumptionsRef(), pf);
02771 }
02772
02773 Theorem ArithTheoremProducer::moveSumConstantRight(const Expr& e) {
02774
02775
02776 if (CHECK_PROOFS) {
02777 CHECK_SOUND(isIneq(e) || e.isEq(), "moveSumConstantRight: input must be Eq or Ineq: " + e.toString());
02778 CHECK_SOUND(isRational(e[0]) || isPlus(e[0]), "moveSumConstantRight: left side must be a canonised sum: " + e.toString());
02779 CHECK_SOUND(isRational(e[1]) && e[1].getRational() == 0, "moveSumConstantRight: right side must be 0: " + e.toString());
02780 }
02781
02782
02783 Rational r = 0;
02784
02785
02786 Expr right = e[0];
02787
02788
02789 vector<Expr> sumTerms;
02790
02791
02792 if (!right.isRational())
02793 for(Expr::iterator it = right.begin(); it != right.end(); it ++) {
02794
02795 if ((*it).isRational()) r = r + (*it).getRational();
02796
02797 else sumTerms.push_back((*it));
02798 }
02799
02800
02801 Expr transformed;
02802 if (sumTerms.size() > 1)
02803
02804 transformed = Expr(e.getKind(), plusExpr(sumTerms), rat(-r));
02805 else
02806
02807 transformed = Expr(e.getKind(), sumTerms[0], rat(-r));
02808
02809
02810
02811 Proof pf;
02812 if (withProof()) pf = newPf("arithm_sum_constant_right", e);
02813
02814
02815 return newRWTheorem(e, transformed, Assumptions::emptyAssump(), pf);
02816 }
02817
02818 Theorem ArithTheoremProducer::eqToIneq(const Expr& e) {
02819
02820
02821 if (CHECK_PROOFS)
02822 CHECK_SOUND(e.isEq(), "eqToIneq: input must be an equality: " + e.toString());
02823
02824
02825 Proof pf;
02826
02827
02828 const Expr& x = e[0];
02829 const Expr& y = e[1];
02830
02831
02832 if (withProof())
02833 pf = newPf("eqToIneq", e);
02834
02835
02836 return newRWTheorem(e, leExpr(x,y).andExpr(geExpr(x,y)), Assumptions::emptyAssump(), pf);
02837 }
02838
02839 Theorem ArithTheoremProducer::dummyTheorem(const Expr& e) {
02840 Proof pf;
02841 return newRWTheorem(e, d_em->trueExpr(), Assumptions::emptyAssump(), pf);
02842 }
02843
02844 Theorem ArithTheoremProducer::oneElimination(const Expr& e) {
02845
02846
02847 if (CHECK_PROOFS)
02848 CHECK_SOUND(isMult(e) &&
02849 e.arity() == 2 &&
02850 e[0].isRational() &&
02851 e[0].getRational() == 1,
02852 "oneElimination: input must be a multiplication by one" + e.toString());
02853
02854
02855 Proof pf;
02856
02857
02858 if (withProof())
02859 pf = newPf("oneElimination", e);
02860
02861
02862 return newRWTheorem(e, e[1], Assumptions::emptyAssump(), pf);
02863 }
02864
02865 Theorem ArithTheoremProducer::clashingBounds(const Theorem& lowerBound, const Theorem& upperBound) {
02866
02867
02868 const Expr& lowerBoundExpr = lowerBound.getExpr();
02869 const Expr& upperBoundExpr = upperBound.getExpr();
02870
02871
02872 if (CHECK_PROOFS) {
02873 CHECK_SOUND(isLE(lowerBoundExpr) || isLT(lowerBoundExpr), "clashingBounds: lowerBound should be >= or > " + lowerBoundExpr.toString());
02874 CHECK_SOUND(isGE(upperBoundExpr) || isGT(upperBoundExpr), "clashingBounds: upperBound should be <= or < " + upperBoundExpr.toString());
02875 CHECK_SOUND(lowerBoundExpr[0].isRational(), "clashingBounds: lowerBound left side should be a rational " + lowerBoundExpr.toString());
02876 CHECK_SOUND(upperBoundExpr[0].isRational(), "clashingBounds: upperBound left side should be a rational " + upperBoundExpr.toString());
02877 CHECK_SOUND(lowerBoundExpr[1] == upperBoundExpr[1], "clashingBounds: bounds not on the same term " + lowerBoundExpr.toString() + ", " + upperBoundExpr.toString());
02878
02879
02880 Rational lowerBoundR = lowerBoundExpr[0].getRational();
02881 Rational upperBoundR = upperBoundExpr[0].getRational();
02882
02883 if (isLE(lowerBoundExpr) && isGE(upperBoundExpr)) {
02884 CHECK_SOUND(upperBoundR < lowerBoundR, "clashingBounds: bounds are satisfiable");
02885 } else {
02886 CHECK_SOUND(upperBoundR <= lowerBoundR, "clashingBounds: bounds are satisfiable");
02887 }
02888 }
02889
02890
02891 Proof pf;
02892
02893 if (withProof())
02894 pf = newPf("clashingBounds", lowerBoundExpr, upperBoundExpr);
02895
02896
02897 Assumptions assumptions;
02898 assumptions.add(lowerBound);
02899 assumptions.add(upperBound);
02900
02901
02902 return newTheorem(d_em->falseExpr(), assumptions, pf);
02903 }
02904
02905 Theorem ArithTheoremProducer::addInequalities(const Theorem& thm1, const Theorem& thm2) {
02906
02907
02908 const Expr& expr1 = thm1.getExpr();
02909 const Expr& expr2 = thm2.getExpr();
02910
02911
02912 if (CHECK_PROOFS) {
02913
02914 CHECK_SOUND(isIneq(expr1), "addInequalities: expecting an inequality for thm1, got " + expr1.toString());
02915 CHECK_SOUND(isIneq(expr2), "addInequalities: expecting an inequality for thm2, got " + expr2.toString());
02916
02917 if (isLE(expr1) || isLT(expr1))
02918 CHECK_SOUND(isLE(expr2) || isLT(expr2), "addInequalities: expr2 should be <(=) also " + expr2.toString());
02919 if (isGE(expr1) || isGT(expr1))
02920 CHECK_SOUND(isGE(expr2) || isGT(expr2), "addInequalities: expr2 should be >(=) also" + expr2.toString());
02921 }
02922
02923
02924 Assumptions a(thm1, thm2);
02925
02926
02927 int kind1 = expr1.getKind();
02928 int kind2 = expr2.getKind();
02929
02930
02931 int kind = (kind1 == kind2) ? kind1 : ((kind1 == LT) || (kind2 == LT))? LT : GT;
02932
02933
02934 Proof pf;
02935 if(withProof()) {
02936 vector<Proof> pfs;
02937 pfs.push_back(thm1.getProof());
02938 pfs.push_back(thm2.getProof());
02939 pf = newPf("addInequalities", expr1, expr2, pfs);
02940 }
02941
02942
02943 Expr leftSide = plusExpr(expr1[0], expr2[0]);
02944 Expr rightSide = plusExpr(expr1[1], expr2[1]);
02945
02946
02947 return newTheorem(Expr(kind, leftSide, rightSide), a, pf);
02948 }
02949
02950 Theorem ArithTheoremProducer::implyWeakerInequality(const Expr& expr1, const Expr& expr2) {
02951
02952
02953 if (CHECK_PROOFS) {
02954
02955
02956 CHECK_SOUND(isIneq(expr1), "implyWeakerInequality: expr1 should be an inequality" + expr1.toString());
02957 CHECK_SOUND(isIneq(expr2), "implyWeakerInequality: expr1 should be an inequality" + expr2.toString());
02958
02959 bool type_less_than = true;
02960
02961
02962 if (isLE(expr1) || isLT(expr1))
02963 CHECK_SOUND(isLE(expr2) || isLT(expr2), "implyWeakerInequality: expr2 should be <(=) also " + expr2.toString());
02964 if (isGE(expr1) || isGT(expr1)) {
02965 CHECK_SOUND(isGE(expr2) || isGT(expr2), "implyWeakerInequality: expr2 should be >(=) also" + expr2.toString());
02966 type_less_than = false;
02967 }
02968
02969
02970 CHECK_SOUND(expr1[0].isRational(), "implyWeakerInequality: expr1 should have a rational on the left side" + expr1.toString());
02971 CHECK_SOUND(expr2[0].isRational(), "implyWeakerInequality: expr2 should have a rational on the left side" + expr2.toString());
02972
02973
02974 CHECK_SOUND(expr1[1] == expr2[1], "implyWeakerInequality: the expression must be the same" + expr1.toString() + " and " + expr2.toString());
02975
02976 Rational expr1rat = expr1[0].getRational();
02977 Rational expr2rat = expr2[0].getRational();
02978
02979
02980
02981 if (type_less_than) {
02982 if (isLE(expr1) || isLT(expr2)) {
02983 CHECK_SOUND(expr2rat < expr1rat, "implyWeakerInequality: the implication doesn't apply" + expr1.toString() + " and " + expr2.toString());
02984 } else {
02985 CHECK_SOUND(expr2rat <= expr1rat, "implyWeakerInequality: the implication doesn't apply" + expr1.toString() + " and " + expr2.toString());
02986 }
02987 } else {
02988 if (isGE(expr1) || isGT(expr2)) {
02989 CHECK_SOUND(expr2rat > expr1rat, "implyWeakerInequality: the implication doesn't apply" + expr1.toString() + " and " + expr2.toString());
02990 } else {
02991 CHECK_SOUND(expr2rat >= expr1rat, "implyWeakerInequality: the implication doesn't apply" + expr1.toString() + " and " + expr2.toString());
02992 }
02993 }
02994 }
02995
02996
02997 Proof pf;
02998 if(withProof()) pf = newPf("implyWeakerInequality", expr1, expr2);
02999
03000
03001 return newTheorem(expr1.impExpr(expr2), Assumptions::emptyAssump(), pf);
03002 }
03003
03004 Theorem ArithTheoremProducer::implyNegatedInequality(const Expr& expr1, const Expr& expr2) {
03005
03006
03007 if (CHECK_PROOFS) {
03008 CHECK_SOUND(isIneq(expr1), "implyNegatedInequality: lowerBound should be an inequality " + expr1.toString());
03009 CHECK_SOUND(isIneq(expr2), "implyNegatedInequality: upperBound should be be an inequality " + expr2.toString());
03010 CHECK_SOUND(expr1[0].isRational(), "implyNegatedInequality: lowerBound left side should be a rational " + expr1.toString());
03011 CHECK_SOUND(expr2[0].isRational(), "implyNegatedInequality: upperBound left side should be a rational " + expr2.toString());
03012 CHECK_SOUND(expr1[1] == expr2[1], "implyNegatedInequality: bounds not on the same term " + expr1.toString() + ", " + expr2.toString());
03013
03014
03015 Rational lowerBoundR = expr1[0].getRational();
03016 Rational upperBoundR = expr2[0].getRational();
03017
03018 if (isLE(expr1) && isGE(expr2))
03019 CHECK_SOUND(upperBoundR < lowerBoundR, "implyNegatedInequality: cant imply negation" + expr1.toString() + ", " + expr2.toString());
03020 if (isLT(expr1) || isGT(expr2))
03021 CHECK_SOUND(upperBoundR <= lowerBoundR, "implyNegatedInequality: cant imply negation" + expr1.toString() + ", " + expr2.toString());
03022 if (isGE(expr1) && isLE(expr2))
03023 CHECK_SOUND(upperBoundR > lowerBoundR, "implyNegatedInequality: cant imply negation" + expr1.toString() + ", " + expr2.toString());
03024 if (isGT(expr1) || isLT(expr2))
03025 CHECK_SOUND(upperBoundR >= lowerBoundR, "implyNegatedInequality: cant imply negation" + expr1.toString() + ", " + expr2.toString());
03026 }
03027
03028
03029 Proof pf;
03030 if (withProof()) pf = newPf("implyNegatedInequality", expr1, expr2);
03031
03032
03033 return newTheorem(expr1.impExpr(expr2.negate()), Assumptions::emptyAssump(), pf);
03034 }
03035
03036 Theorem ArithTheoremProducer::trustedRewrite(const Expr& expr1, const Expr& expr2) {
03037
03038
03039 Proof pf;
03040
03041
03042 if (withProof()) pf = newPf("trustedRewrite", expr1, expr2);
03043
03044
03045 return newRWTheorem(expr1, expr2, Assumptions::emptyAssump(), pf);
03046
03047 }
03048
03049 Theorem ArithTheoremProducer::integerSplit(const Expr& intVar, const Rational& intPoint) {
03050
03051
03052 if (CHECK_PROOFS) {
03053 CHECK_SOUND(intPoint.isInteger(), "integerSplit: we can only split on integer points, given" + intPoint.toString());
03054 }
03055
03056
03057 const Expr& split = Expr(IS_INTEGER, intVar).impExpr(leExpr(intVar, rat(intPoint)).orExpr(geExpr(intVar, rat(intPoint + 1))));
03058
03059
03060 Proof pf;
03061 if (withProof()) pf = newPf("integerSplit", intVar, rat(intPoint));
03062
03063
03064 return newTheorem(split, Assumptions::emptyAssump(), pf);
03065 }
03066
03067
03068 Theorem ArithTheoremProducer::rafineStrictInteger(const Theorem& isIntConstrThm, const Expr& constr) {
03069
03070
03071
03072 if (CHECK_PROOFS) {
03073
03074 CHECK_SOUND(isIneq(constr), "rafineStrictInteger: expected a constraint got : " + constr.toString());
03075 CHECK_SOUND(isIntConstrThm.getExpr()[0] == constr[1], "rafineStrictInteger: proof of intger doesn't correspond to the constarint right side");
03076 CHECK_SOUND(constr[0].isRational(), "rafineStrictInteger: right side of the constraint muts be a rational");
03077 }
03078
03079
03080 Rational bound = constr[0].getRational();
03081
03082
03083 int kind = constr.getKind();
03084
03085
03086 switch (kind) {
03087 case LT:
03088 kind = LE;
03089 if (bound.isInteger()) bound ++;
03090 else bound = ceil(bound);
03091 break;
03092 case LE:
03093 kind = LE;
03094 if (!bound.isInteger()) bound = ceil(bound);
03095 break;
03096 case GT:
03097 kind = GE;
03098 if (bound.isInteger()) bound --;
03099 else bound = floor(bound);
03100 break;
03101 case GE:
03102 kind = GE;
03103 if (!bound.isInteger()) bound = floor(bound);
03104 break;
03105 }
03106
03107
03108 Expr newConstr(kind, rat(bound), constr[1]);
03109
03110
03111 const Assumptions& assump(isIntConstrThm.getAssumptionsRef());
03112
03113
03114 Proof pf;
03115 if (withProof()) pf = newPf("rafineStrictInteger", constr, isIntConstrThm.getProof());
03116
03117
03118 return newRWTheorem(constr, newConstr, assump, pf);
03119 }
03120
03121
03122
03123 Theorem ArithTheoremProducer::simpleIneqInt(const Expr& ineq, const Theorem& isIntRHS)
03124 {
03125 DebugAssert(false, "Not implemented!!!");
03126 return Theorem();
03127 }
03128
03129
03130
03131
03132
03133 Theorem ArithTheoremProducer::intEqualityRationalConstant(const Theorem& isIntConstrThm, const Expr& constr) {
03134 DebugAssert(false, "Not implemented!!!");
03135 return Theorem();
03136 }
03137
03138 Theorem ArithTheoremProducer::cycleConflict(const vector<Theorem>& inequalitites) {
03139 DebugAssert(false, "Not implemented!!!");
03140 return Theorem();
03141 }
03142
03143 Theorem ArithTheoremProducer::implyEqualities(const vector<Theorem>& inequalitites) {
03144 DebugAssert(false, "Not implemented!!!");
03145 return Theorem();
03146 }
03147
03148
03149
03150
03151
03152 Theorem ArithTheoremProducer::lessThanToLERewrite(const Expr& ineq,
03153 const Theorem& isIntLHS,
03154 const Theorem& isIntRHS,
03155 bool changeRight) {
03156
03157 const Expr& isIntLHSexpr = isIntLHS.getExpr();
03158 const Expr& isIntRHSexpr = isIntRHS.getExpr();
03159
03160 if(CHECK_PROOFS) {
03161 CHECK_SOUND(isLT(ineq), "ArithTheoremProducerOld::LTtoLE: ineq must be <");
03162
03163 CHECK_SOUND(isIntPred(isIntLHSexpr) && isIntLHSexpr[0] == ineq[0],
03164 "ArithTheoremProducerOld::lessThanToLE: bad integrality check:\n"
03165 " ineq = "+ineq.toString()+"\n isIntLHS = "
03166 +isIntLHSexpr.toString());
03167 CHECK_SOUND(isIntPred(isIntRHSexpr) && isIntRHSexpr[0] == ineq[1],
03168 "ArithTheoremProducerOld::lessThanToLE: bad integrality check:\n"
03169 " ineq = "+ineq.toString()+"\n isIntRHS = "
03170 +isIntRHSexpr.toString());
03171 }
03172
03173 vector<Theorem> thms;
03174 thms.push_back(isIntLHS);
03175 thms.push_back(isIntRHS);
03176 Assumptions a(thms);
03177 Proof pf;
03178 Expr le = changeRight? leExpr(ineq[0], ineq[1] + rat(-1)) : leExpr(ineq[0] + rat(1), ineq[1]);
03179 if(withProof()) {
03180 vector<Proof> pfs;
03181 pfs.push_back(isIntLHS.getProof());
03182 pfs.push_back(isIntRHS.getProof());
03183 pf = newPf(changeRight? "lessThan_To_LE_rhs_rwr" : "lessThan_To_LE_lhs_rwr", ineq, le, pfs);
03184 }
03185
03186 return newRWTheorem(ineq, le, a, pf);
03187 }
03188
03189
03190 Theorem ArithTheoremProducer::splitGrayShadowSmall(const Theorem& gThm) {
03191 DebugAssert(false, "Not implemented!!!");
03192 return Theorem();
03193 }
03194
03195 Theorem ArithTheoremProducer::implyWeakerInequalityDiffLogic(const std::vector<Theorem>& antecedentThms, const Expr& implied) {
03196 DebugAssert(false, "Not implemented!!!");
03197 return Theorem();
03198 }
03199
03200 Theorem ArithTheoremProducer::implyNegatedInequalityDiffLogic(const std::vector<Theorem>& antecedentThms, const Expr& implied) {
03201 DebugAssert(false, "Not implemented!!!");
03202 return Theorem();
03203 }
03204
03205 Theorem ArithTheoremProducer::expandGrayShadowRewrite(const Expr& theShadow) {
03206 DebugAssert(false, "Not implemented!!!");
03207 return Theorem();
03208 }
03209
03210 Theorem ArithTheoremProducer::compactNonLinearTerm(const Expr& nonLinear) {
03211 DebugAssert(false, "Not implemented!!!");
03212 return Theorem();
03213 }
03214
03215 Theorem ArithTheoremProducer::nonLinearIneqSignSplit(const Theorem& ineqThm) {
03216 DebugAssert(false, "Not implemented!!!");
03217 return Theorem();
03218 }
03219
03220 Theorem ArithTheoremProducer::implyDiffLogicBothBounds(const Expr& x,
03221 std::vector<Theorem>& c1_le_x, Rational c1,
03222 std::vector<Theorem>& x_le_c2, Rational c2) {
03223 DebugAssert(false, "Not implemented!!!");
03224 return Theorem();
03225 }
03226
03227 Theorem ArithTheoremProducer::addInequalities(const vector<Theorem>& thms) {
03228 DebugAssert(false, "Not implemented!!!");
03229 return Theorem();
03230 }
03231
03232 Theorem ArithTheoremProducer::powerOfOne(const Expr& e) {
03233 DebugAssert(false, "Not implemented!!!");
03234 return Theorem();
03235 }
03236
03237
03238
03239
03240
03241
03242
03243 Theorem ArithProofRules::rewriteLeavesConst(const Expr& e) {
03244 DebugAssert(false, "Not implemented!!!");
03245 return Theorem();
03246 }