CVC3

search_theorem_producer.cpp

Go to the documentation of this file.
00001 /*****************************************************************************/
00002 /*!
00003  * \file search_theorem_producer.cpp
00004  * \brief Implementation of the proof rules for the simple search engine
00005  * 
00006  * Author: Sergey Berezin
00007  * 
00008  * Created: Mon Feb 24 14:51:51 2003
00009  *
00010  * <hr>
00011  *
00012  * License to use, copy, modify, sell and/or distribute this software
00013  * and its documentation for any purpose is hereby granted without
00014  * royalty, subject to the terms and conditions defined in the \ref
00015  * LICENSE file provided with this distribution.
00016  * 
00017  * <hr>
00018  * 
00019  */
00020 /*****************************************************************************/
00021 
00022 #include "search.h"
00023 #include "theory_core.h"
00024 #include "theorem_manager.h"
00025 #include "common_proof_rules.h"
00026 #include "command_line_flags.h"
00027 #include "theory_arith.h"
00028 // UNCOMMENT THIS FOR LFSC
00029 #include "LFSCPrinter.h" // by liana for LFSC conversion
00030 
00031 #define _CVC3_TRUSTED_
00032 #include "search_theorem_producer.h"
00033 
00034 
00035 using namespace std;
00036 using namespace CVC3;
00037 
00038 
00039 /////////////////////////////////////////////////////////////////////////////
00040 // class SearchEngine trusted methods
00041 /////////////////////////////////////////////////////////////////////////////
00042 
00043 
00044 
00045 SearchEngineRules*
00046 SearchEngine::createRules() {
00047   return new SearchEngineTheoremProducer(d_core->getTM());
00048 }
00049 
00050 
00051 // hack for printing original assumptions in LFSC by liana
00052 bool lfsc_called = false;
00053 SearchEngine* search_engine;
00054 
00055 SearchEngineRules*
00056 SearchEngine::createRules(SearchEngine* s_eng) {
00057   search_engine = s_eng;
00058   return new SearchEngineTheoremProducer(d_core->getTM());
00059 }
00060 
00061 
00062 SearchEngineTheoremProducer::SearchEngineTheoremProducer(TheoremManager* tm)
00063   : TheoremProducer(tm), d_commonRules(tm->getRules())
00064 { }
00065 
00066 
00067 /////////////////////////////////////////////////////////////////////////////
00068 // Proof rules
00069 /////////////////////////////////////////////////////////////////////////////
00070 
00071 // Proof by contradiction: !A |- FALSE ==> |- A.  "!A" doesn't
00072 // have to be present in the assumptions.
00073 Theorem
00074 SearchEngineTheoremProducer::proofByContradiction(const Expr& a,
00075                                                   const Theorem& pfFalse) {
00076   if(CHECK_PROOFS)
00077     CHECK_SOUND(pfFalse.getExpr().isFalse(),
00078                 "proofByContradiction: pfFalse = : " + pfFalse.toString());
00079   Expr not_a(!a);
00080   Assumptions assump(pfFalse.getAssumptionsRef() - not_a);
00081   Proof pf;
00082   if(withProof()) {
00083     // TODO: optimize with 1 traversal?
00084     Theorem thm(pfFalse.getAssumptionsRef()[not_a]);
00085     Proof u; // proof label for !aLFSCL
00086     if(!thm.isNull()) u = thm.getProof();
00087     // Proof compaction: if u is Null, use "FALSE => A" rule
00088     if(u.isNull()){
00089       pf = newPf("false_implies_anything", a, pfFalse.getProof());
00090       if(!lfsc_called){
00091         satProof(a, pf);
00092       }
00093     }
00094     else
00095       pf = newPf("pf_by_contradiction", a,
00096                  // LAMBDA-abstraction (LAMBDA (u: !a): pfFalse)
00097                  newPf(u, not_a, pfFalse.getProof()));
00098   }
00099   return newTheorem(a, assump, pf);
00100 }
00101     
00102 // Similar rule, only negation introduction:
00103 // A |- FALSE ==> !A
00104 Theorem
00105 SearchEngineTheoremProducer::negIntro(const Expr& not_a,
00106                                       const Theorem& pfFalse) {
00107   if(CHECK_PROOFS) {
00108     CHECK_SOUND(pfFalse.getExpr().isFalse(),
00109                 "negIntro: pfFalse = : " + pfFalse.toString());
00110     CHECK_SOUND(not_a.isNot(), "negIntro: not_a = "+not_a.toString());
00111   }
00112 
00113   Expr a(not_a[0]);
00114   Assumptions assump(pfFalse.getAssumptionsRef() - a);
00115   Proof pf;
00116   if(withProof()) {
00117     Theorem thm(pfFalse.getAssumptionsRef()[a]);
00118     Proof u; // proof label for 'a'
00119     if(!thm.isNull()) u = thm.getProof();
00120     // Proof compaction: if u is Null, use "FALSE => !A" rule
00121     if(u.isNull())
00122       pf = newPf("false_implies_anything", not_a, pfFalse.getProof());
00123 
00124     else
00125       pf = newPf("neg_intro", not_a,
00126                  // LAMBDA-abstraction (LAMBDA (u: a): pfFalse)
00127                  newPf(u, a, pfFalse.getProof()));
00128   }
00129   return newTheorem(not_a, assump, pf);
00130 }
00131     
00132 
00133 // Case split: u1:A |- C, u2:!A |- C  ==>  |- C
00134 Theorem
00135 SearchEngineTheoremProducer::caseSplit(const Expr& a,
00136                                        const Theorem& a_proves_c,
00137                                        const Theorem& not_a_proves_c) {
00138   Expr c(a_proves_c.getExpr());
00139 
00140   if(CHECK_PROOFS) {
00141     CHECK_SOUND(c == not_a_proves_c.getExpr(), 
00142                 "caseSplit: conclusions differ:\n  positive case C = "
00143                 + c.toString() + "\n  negative case C = "
00144                 + not_a_proves_c.getExpr().toString());
00145     // The opposite assumption should not appear in the theorems
00146     // Actually, this doesn't violate soundness, no reason to check
00147 //     CHECK_SOUND(a_proves_c.getAssumptions()[!a].isNull(), 
00148 //              "caseSplit: wrong assumption: " + (!a).toString()
00149 //              +"\n in "+a_proves_c.toString());
00150 //     CHECK_SOUND(not_a_proves_c.getAssumptions()[a].isNull(), 
00151 //              "caseSplit: wrong assumption: " + a.toString()
00152 //              +"\n in "+not_a_proves_c.toString());
00153   }
00154 
00155   const Assumptions& a1(a_proves_c.getAssumptionsRef());
00156   const Assumptions& a2(not_a_proves_c.getAssumptionsRef());
00157   Assumptions a3 = a1 - a;
00158   Assumptions a4 = a2 - !a;
00159 
00160   // Proof compaction: if either theorem proves C without a or !a,
00161   // then just use that theorem.  This only works if assumptions are
00162   // active.
00163 
00164   if (a1 == a3) return a_proves_c;
00165   if (a2 == a4) return not_a_proves_c;
00166 
00167   // No easy way out.  Do the work.
00168   Proof pf;
00169   a3.add(a4);
00170 
00171   if(withProof()) {
00172     // Create lambda-abstractions
00173     vector<Proof> pfs;
00174     pfs.push_back(newPf(a1[a].getProof(), 
00175                         a, a_proves_c.getProof()));
00176     pfs.push_back(newPf(a2[!a].getProof(), 
00177                         !a, not_a_proves_c.getProof()));
00178     pf = newPf("case_split", a, c, pfs);
00179   }
00180   return newTheorem(c, a3, pf);
00181 }
00182 
00183 // Conflict clause rule: 
00184 // Gamma, A_1,...,A_n |- B ==> Gamma |- (OR B A_1 ... A_n)
00185 // The assumptions A_i are given by the vector 'lits'.
00186 // If B==FALSE, it is omitted from the result.
00187 
00188 // NOTE: here "!A_i" means an inverse of A_i, not just a negation.
00189 // That is, if A_i is NOT C, then !A_i is C.
00190 
00191 // verification function used by conflictClause
00192 void SearchEngineTheoremProducer::verifyConflict(const Theorem& thm, 
00193                                                  TheoremMap& m) {
00194   const Assumptions& a(thm.getAssumptionsRef());
00195   const Assumptions::iterator iend = a.end();
00196   for (Assumptions::iterator i = a.begin(); 
00197        i != iend; ++i) {
00198     CHECK_SOUND(!i->isNull(),
00199                 "SearchEngineTheoremProducer::conflictClause: "
00200                 "Found null theorem");
00201     if (!i->isRefl() && !i->isFlagged()) {
00202       i->setFlag();
00203       if (m.count(*i) == 0) {
00204         CHECK_SOUND(!i->isAssump(),
00205                     "SearchEngineTheoremProducer::conflictClause: "
00206                     "literal and gamma sets do not form a complete "
00207                     "cut of Theorem assumptions. Stray theorem: \n"
00208                     +i->toString());
00209         verifyConflict(*i, m);
00210       }
00211       else {
00212         m[*i] = true;
00213       }
00214     }
00215   }
00216 }
00217 
00218 
00219 Theorem
00220 SearchEngineTheoremProducer::
00221 conflictClause(const Theorem& thm, const vector<Theorem>& lits, 
00222                const vector<Theorem>& gamma) {
00223   //  TRACE("search proofs", "conflictClause(", thm.getExpr(), ") {");
00224   IF_DEBUG(if(debugger.trace("search proofs")) {
00225     ostream& os = debugger.getOS();
00226     os << "lits = [";
00227     for(vector<Theorem>::const_iterator i=lits.begin(), iend=lits.end();
00228         i!=iend; ++i)
00229       os << i->getExpr() << ",\n";
00230     os << "]\n\ngamma = [";
00231     for(vector<Theorem>::const_iterator i=gamma.begin(), iend=gamma.end();
00232         i!=iend; ++i)
00233       os << i->getExpr() << ",\n";
00234     os << "]" << endl;
00235   });
00236   bool checkProofs(CHECK_PROOFS);
00237   // This rule only makes sense when runnnig with assumptions
00238   if(checkProofs) {
00239     CHECK_SOUND(withAssumptions(),
00240                 "conflictClause: called while running without assumptions");
00241   }
00242 
00243   // Assumptions aOrig(thm.getAssumptions());
00244 
00245   vector<Expr> literals;
00246   vector<Proof> u; // Vector of proof labels
00247   literals.reserve(lits.size() + 1);
00248   u.reserve(lits.size());
00249   const vector<Theorem>::const_iterator iend = lits.end();
00250   for(vector<Theorem>::const_iterator i=lits.begin(); i!=iend; ++i) {
00251     Expr neg(i->getExpr().negate());
00252 
00253     literals.push_back(neg);
00254     if(withProof()) u.push_back(i->getProof());
00255   }
00256 
00257   if(checkProofs) {
00258     TheoremMap m;
00259     //    TRACE_MSG("search proofs", "adding gamma to m: {");
00260     for(vector<Theorem>::const_iterator i = gamma.begin();
00261         i != gamma.end(); ++i) {
00262       //      TRACE("search proofs", "m[", *i, "]");
00263       m[*i] = false;
00264     }
00265     //    TRACE_MSG("search proofs", "}");
00266 
00267     for(vector<Theorem>::const_iterator i = lits.begin(); i!=iend; ++i) {
00268       //      TRACE("search proofs", "check lit: ", *i, "");
00269       CHECK_SOUND(m.count(*i) == 0, 
00270                   "SearchEngineTheoremProducer::conflictClause: "
00271                   "literal and gamma sets are not disjoint: lit = "
00272                   +i->toString());
00273       m[*i] = false;
00274     }
00275     thm.clearAllFlags();
00276     verifyConflict(thm, m);
00277     TheoremMap::iterator t = m.begin(), tend = m.end();
00278     for (; t != tend; ++t) {
00279       CHECK_SOUND(t->second == true,
00280                   "SearchEngineTheoremProducer::conflictClause: "
00281                   "literal or gamma set contains extra element : "
00282                   + t->first.toString());
00283     }
00284   }
00285  
00286   Assumptions a(gamma);
00287 
00288   if(!thm.getExpr().isFalse())
00289     literals.push_back(thm.getExpr());
00290 
00291   Proof pf;
00292   if(withProof()) {
00293     if(lits.size()>0) {
00294       vector<Expr> assump;
00295       // If assumptions are not leaves, we need to create new
00296       // variables for them and substitute them for their proofs in
00297       // the proof term
00298       ExprHashMap<Expr> subst;
00299       DebugAssert(u.size() == lits.size(), "");
00300       for(size_t i=0, iend=lits.size(); i<iend; ++i) {
00301         const Expr& e(lits[i].getExpr());
00302         assump.push_back(e);
00303         Proof& v = u[i];
00304         if(!v.getExpr().isVar()) {
00305           Proof label = newLabel(e);
00306           subst[v.getExpr()] = label.getExpr();
00307           v = label;
00308         }
00309       }
00310       Proof body(thm.getProof());
00311       if(!subst.empty())
00312         body = Proof(body.getExpr().substExpr(subst));
00313       pf = newPf("conflict_clause", newPf(u, assump, body));
00314     }
00315     else
00316       pf = newPf("false_to_empty_or", thm.getProof());
00317   }
00318   Theorem res(newTheorem(Expr(OR, literals, d_em), a, pf));
00319   //  TRACE("search proofs", "conflictClause => ", res.getExpr(), " }");
00320   return res;
00321 }
00322 
00323 
00324 // Theorem
00325 // SearchEngineTheoremProducer::
00326 // conflictClause(const Theorem& thm, const vector<Expr>& lits) {
00327 //   bool checkProofs(CHECK_PROOFS);
00328 //   // This rule only makes sense when runnnig with assumptions
00329 //   if(checkProofs) {
00330 //     CHECK_SOUND(withAssumptions(),
00331 //              "conflictClause: called while running without assumptions");
00332 //   }
00333 
00334 //   Assumptions aOrig(thm.getAssumptions());
00335 
00336 //   vector<Expr> literals;
00337 //   vector<Expr> negations;
00338 //   vector<Proof> u; // Vector of proof labels
00339 //   literals.reserve(lits.size() + 1);
00340 //   negations.reserve(lits.size());
00341 //   u.reserve(lits.size());
00342 //   for(vector<Expr>::const_iterator i=lits.begin(), iend=lits.end();
00343 //       i!=iend; ++i) {
00344 //     Expr neg(i->isNot()? (*i)[0] : !(*i));
00345 //     if(checkProofs)
00346 //       CHECK_SOUND(!aOrig[neg].isNull(), 
00347 //                "SearchEngineTheoremProducer::conflictClause: "
00348 //                "literal is not in the set of assumptions: neg = "
00349 //                +neg.toString() + "\n Theorem = " + thm.toString());
00350 //     literals.push_back(*i);
00351 //     negations.push_back(neg);
00352 //     if(withProof()) u.push_back(aOrig[neg].getProof());
00353 //   }
00354 
00355 //   Assumptions a = aOrig - negations;
00356 
00357 //   if(!thm.getExpr().isFalse())
00358 //     literals.push_back(thm.getExpr());
00359 
00360 //   Proof pf;
00361 //   if(withProof()) {
00362 //     if(lits.size()>0)
00363 //       pf = newPf("conflict_clause", newPf(u, literals, thm.getProof()));
00364 //     else
00365 //       pf = newPf("false_to_empty_or", thm.getProof());
00366 //   }
00367 //  // Use ExprManager in newExpr, since literals may be empty
00368 //   return newTheorem(Expr(d_em, OR, literals), a, pf);
00369 // }
00370 
00371 
00372 // "Cut" rule: { G_i |- A_i };  G', { A_i } |- B ==> union(G_i)+G' |- B.
00373 Theorem
00374 SearchEngineTheoremProducer::
00375 cutRule(const vector<Theorem>& thmsA,
00376         const Theorem& as_prove_b) {
00377   if(CHECK_PROOFS)
00378     CHECK_SOUND(withAssumptions(),
00379                 "cutRule called without assumptions activated");
00380   // Optimization: use only those theorems that occur in B's assumptions.
00381   // *** No, take it back, it's a mis-optimization.  Most of the time,
00382   // cutRule is applied when we *know* thmsA are present in the
00383   // assumptions of 'as_proof_b'.
00384 
00385   Proof pf;
00386   vector<Expr> exprs;
00387   exprs.reserve(thmsA.size() + 1);
00388   const vector<Theorem>::const_iterator iend = thmsA.end();
00389   for(vector<Theorem>::const_iterator i=thmsA.begin(); i!=iend; ++i) {
00390     exprs.push_back(i->getExpr());
00391   }
00392 
00393   Assumptions a(thmsA); // add the As
00394   a.add(as_prove_b.getAssumptionsRef() - exprs); // Add G'
00395   
00396   if(withProof()) {
00397     vector<Proof> pfs;
00398     pfs.reserve(thmsA.size() + 1);
00399     for(vector<Theorem>::const_iterator i = thmsA.begin(); i != iend; ++i) {
00400       pfs.push_back(i->getProof());
00401     }
00402     exprs.push_back(as_prove_b.getExpr());
00403     pfs.push_back(as_prove_b.getProof());
00404     pf = newPf("cut_rule",exprs,pfs);
00405   }
00406   return newTheorem(as_prove_b.getExpr(), a, pf);
00407 }
00408 
00409 
00410 void 
00411 SearchEngineTheoremProducer::checkSoundNoSkolems(const Expr& e, 
00412                                                  ExprMap<bool>& visited,
00413                                                  const ExprMap<bool>& skolems)
00414 {
00415   if(visited.count(e)>0)
00416     return;
00417   else
00418     visited[e] = true;
00419   CHECK_SOUND(skolems.count(e) == 0, 
00420               "skolem constant found in axioms of false theorem: "
00421               + e.toString());
00422   for(Expr::iterator it = e.begin(), end = e.end(); it!= end; ++it)
00423     checkSoundNoSkolems(*it, visited, skolems);
00424   if(e.getKind() == FORALL || e.getKind() == EXISTS)
00425     checkSoundNoSkolems(e.getBody(), visited, skolems);       
00426 }
00427 
00428 void 
00429 SearchEngineTheoremProducer::checkSoundNoSkolems(const Theorem& t, 
00430                                                  ExprMap<bool>& visited,
00431                                                  const ExprMap<bool>& skolems)
00432 {
00433   if(t.isRefl() || t.isFlagged())
00434     return;
00435   t.setFlag();
00436   if(t.isAssump())
00437     checkSoundNoSkolems(t.getExpr(), visited, skolems);
00438   else
00439   {
00440     const Assumptions& a(t.getAssumptionsRef());
00441     Assumptions::iterator it = a.begin(), end = a.end();
00442     for(; it!=end; ++it)
00443       checkSoundNoSkolems(*it, visited, skolems);
00444    }
00445 }
00446 
00447 /*! Eliminate skolem axioms: 
00448  * Gamma, Delta |- false => Gamma|- false 
00449  * where Delta is a set of skolem axioms {|-Exists(x) phi (x) => phi(c)}
00450  * and gamma does not contain any of the skolem constants c.
00451  */
00452 
00453 Theorem 
00454 SearchEngineTheoremProducer::eliminateSkolemAxioms(const Theorem& tFalse, 
00455                                             const std::vector<Theorem>& delta)
00456 {
00457   TRACE("skolem", "=>eliminateSkolemAxioms ", delta.size(), "{");
00458   if(delta.empty())
00459   {
00460     TRACE("skolem",  "eliminateSkolemAxioms","" , "}");
00461     return tFalse;
00462   }
00463   const Expr& falseExpr = tFalse.getExpr();
00464   if(CHECK_PROOFS) {
00465     CHECK_SOUND(falseExpr.isFalse(),
00466                 "eliminateSkolemAxiom called on non-false theorem");
00467     ExprMap<bool> visited;
00468     ExprMap<bool> skolems;
00469     vector<Theorem>::const_iterator it = delta.begin(), end = delta.end();
00470     for(; it!=end; ++it) {
00471       CHECK_SOUND(it->isRewrite(),
00472                   "eliminateSkolemAxioms(): Skolem axiom is not "
00473                   "an IFF: "+it->toString());
00474       const Expr& ex = it->getLHS();
00475       CHECK_SOUND(ex.isExists(), 
00476                   "Did not receive skolem axioms in Delta"
00477                   " of eliminateSkolemAxioms" + it->toString());
00478       // Collect the Skolem constants for further soundness checks
00479       for(unsigned int j=0; j<ex.getVars().size(); j++) {
00480         Expr sk_var(ex.skolemExpr(j));
00481         if(sk_var.getType().isBool()) {
00482           sk_var = d_em->newLeafExpr(sk_var.mkOp());
00483         }
00484         skolems[sk_var] = true;
00485         TRACE("skolem", ">> Eliminating variable: ", sk_var, "<<");
00486       }
00487     }
00488     tFalse.clearAllFlags();
00489     checkSoundNoSkolems(tFalse, visited, skolems);
00490   }
00491   Proof pf;
00492   if(!withProof()) return tFalse;
00493   else 
00494     {
00495       Proof origFalse = tFalse.getProof();
00496       std::vector<Proof>skolemizeLabels;
00497       std::vector<Expr> exprs;
00498       for(unsigned int i=0; i<delta.size(); i++)
00499         {
00500           exprs.push_back(delta[i].getExpr());
00501           skolemizeLabels.push_back(delta[i].getProof());
00502         }
00503       pf = newPf(skolemizeLabels, exprs, origFalse);
00504     }
00505   TRACE("skolem",  "eliminateSkolemAxioms","" , "}");
00506   return newTheorem(tFalse.getExpr(), tFalse.getAssumptionsRef(), pf);
00507 }
00508 
00509 
00510 Theorem
00511 SearchEngineTheoremProducer::unitProp(const std::vector<Theorem>& thms,
00512                                       const Theorem& clause,
00513                                       unsigned i) {
00514   Expr e(clause.getExpr());
00515   if(CHECK_PROOFS) {
00516     // Soundness check: first, check the form of the 'clause' theorem
00517     CHECK_SOUND(e.isOr() && e.arity() > (int)i,
00518                 "SearchEngineTheoremProducer::unitProp: bad theorem or i="
00519                 +int2string(i)+" > arity="+int2string(e.arity())
00520                 +" in clause = " + clause.toString());
00521     // Now, check correspondence of thms to the disjunction
00522     CHECK_SOUND(((int)thms.size()) == e.arity() - 1,
00523                 "SearchEngineTheoremProducer::unitProp: "
00524                 "wrong number of theorems"
00525                 "\n  thms.size = " + int2string(thms.size())
00526                 +"\n  clause.arity = " + int2string(e.arity()));
00527 
00528     for(unsigned j=0,k=0; j<thms.size(); j++) {
00529       if(j!=i) {
00530         Expr ej(e[j]), ek(thms[k].getExpr());
00531         CHECK_SOUND((ej.isNot() && ej[0] == ek) || (ek.isNot() && ej == ek[0]),
00532                     "SearchEngineTheoremProducer::unitProp: "
00533                     "wrong theorem["+int2string(k)+"]"
00534                     "\n  thm = " + thms[k].toString() +
00535                     "\n  literal = " + e[j].toString() +
00536                     "\n  clause = " + clause.toString());
00537         k++;
00538       }
00539     }
00540   }
00541 
00542   Assumptions a(thms);
00543   a.add(clause);
00544   Proof pf;
00545 
00546   if(withProof()) {
00547     vector<Proof> pfs;
00548     vector<Expr> exprs;
00549     exprs.reserve(thms.size() + 1);
00550     pfs.reserve(thms.size()+1);
00551     const vector<Theorem>::const_iterator iend = thms.end();
00552     for(vector<Theorem>::const_iterator i=thms.begin(); i!=iend; ++i) {
00553       exprs.push_back(i->getExpr());
00554       pfs.push_back(i->getProof());
00555     }
00556     exprs.push_back(clause.getExpr());
00557     pfs.push_back(clause.getProof());
00558     pf = newPf("unit_prop", exprs, pfs);
00559   }
00560   return newTheorem(e[i], a, pf);
00561 }
00562 
00563 Theorem
00564 SearchEngineTheoremProducer::propAndrAF(const Theorem& andr_th,
00565                                         bool left,
00566                                         const Theorem& b_th) {
00567   const Expr& andr_e(andr_th.getExpr());
00568   if(CHECK_PROOFS) {
00569     CHECK_SOUND(andr_e.getKind() == AND_R &&
00570                 ((left && b_th.refutes(andr_e[1])) ||
00571                  (!left && b_th.refutes(andr_e[2]))),
00572                 "SearchEngineTheoremProducer::propAndrAF");
00573   }
00574 
00575   Assumptions a(andr_th, b_th);
00576   Proof pf;
00577 
00578   if(withProof()) {
00579     vector<Proof> pfs;
00580     vector<Expr> exprs;
00581     exprs.push_back(andr_th.getExpr());
00582     exprs.push_back(b_th.getExpr());
00583     pfs.push_back(andr_th.getProof());
00584     pfs.push_back(b_th.getProof());
00585     // can we note which branch to take?
00586     pf = newPf("prop_andr_af", exprs, pfs);
00587   }
00588 
00589   return newTheorem(andr_e[0].negate(), a, pf);
00590 }
00591 
00592 Theorem
00593 SearchEngineTheoremProducer::propAndrAT(const Theorem& andr_th,
00594                                         const Theorem& l_th,
00595                                         const Theorem& r_th) {
00596   const Expr& andr_e(andr_th.getExpr());
00597   if(CHECK_PROOFS) {
00598     CHECK_SOUND(andr_e.getKind() == AND_R &&
00599                 l_th.proves(andr_e[1]) && r_th.proves(andr_e[2]),
00600                 "SearchEngineTheoremProducer::propAndrAT");
00601   }
00602 
00603   Assumptions a(andr_th, l_th);
00604   a.add(r_th);
00605   Proof pf;
00606 
00607   if(withProof()) {
00608     vector<Proof> pfs;
00609     vector<Expr> exprs;
00610     exprs.push_back(andr_th.getExpr());
00611     exprs.push_back(l_th.getExpr());
00612     exprs.push_back(r_th.getExpr());
00613     pfs.push_back(andr_th.getProof());
00614     pfs.push_back(l_th.getProof());
00615     pfs.push_back(r_th.getProof());
00616     pf = newPf("prop_andr_at", exprs, pfs);
00617   }
00618 
00619   return newTheorem(andr_e[0], a, pf);
00620 }
00621 
00622 void
00623 SearchEngineTheoremProducer::propAndrLRT(const Theorem& andr_th,
00624                                          const Theorem& a_th,
00625                                          Theorem* l_th,
00626                                          Theorem* r_th) {
00627   const Expr& andr_e(andr_th.getExpr());
00628   if(CHECK_PROOFS) {
00629     CHECK_SOUND(andr_e.getKind() == AND_R && a_th.proves(andr_e[0]),
00630                 "SearchEngineTheoremProducer::propAndrLRT");
00631   }
00632 
00633   Assumptions a(andr_th, a_th);
00634   Proof pf;
00635 
00636   if(withProof()) {
00637     vector<Proof> pfs;
00638     vector<Expr> exprs;
00639     exprs.push_back(andr_th.getExpr());
00640     exprs.push_back(a_th.getExpr());
00641     pfs.push_back(andr_th.getProof());
00642     pfs.push_back(a_th.getProof());
00643     pf = newPf("prop_andr_lrt", exprs, pfs);
00644   }
00645 
00646   if (l_th) *l_th = newTheorem(andr_e[1], a, pf);
00647   if (r_th) *r_th = newTheorem(andr_e[2], a, pf);
00648 }
00649 
00650 Theorem
00651 SearchEngineTheoremProducer::propAndrLF(const Theorem& andr_th,
00652                                         const Theorem& a_th,
00653                                         const Theorem& r_th) {
00654   const Expr& andr_e(andr_th.getExpr());
00655   if(CHECK_PROOFS) {
00656     CHECK_SOUND(andr_e.getKind() == AND_R &&
00657                 a_th.refutes(andr_e[0]) && r_th.proves(andr_e[2]),
00658                 "SearchEngineTheoremProducer::propAndrLF");
00659   }
00660 
00661   Assumptions a(andr_th, a_th);
00662   a.add(r_th);
00663   Proof pf;
00664 
00665   if(withProof()) {
00666     vector<Proof> pfs;
00667     vector<Expr> exprs;
00668     exprs.push_back(andr_th.getExpr());
00669     exprs.push_back(a_th.getExpr());
00670     exprs.push_back(r_th.getExpr());
00671     pfs.push_back(andr_th.getProof());
00672     pfs.push_back(a_th.getProof());
00673     pfs.push_back(r_th.getProof());
00674     pf = newPf("prop_andr_lf", exprs, pfs);
00675   }
00676 
00677   return newTheorem(andr_e[1].negate(), a, pf);
00678 }
00679 
00680 Theorem
00681 SearchEngineTheoremProducer::propAndrRF(const Theorem& andr_th,
00682                                         const Theorem& a_th,
00683                                         const Theorem& l_th) {
00684   const Expr& andr_e(andr_th.getExpr());
00685   if(CHECK_PROOFS) {
00686     CHECK_SOUND(andr_e.getKind() == AND_R &&
00687                 a_th.refutes(andr_e[0]) && l_th.proves(andr_e[1]),
00688                 "SearchEngineTheoremProducer::propAndrRF");
00689   }
00690 
00691   Assumptions a(andr_th, a_th);
00692   a.add(l_th);
00693   Proof pf;
00694 
00695   if(withProof()) {
00696     vector<Proof> pfs;
00697     vector<Expr> exprs;
00698     exprs.push_back(andr_th.getExpr());
00699     exprs.push_back(a_th.getExpr());
00700     exprs.push_back(l_th.getExpr());
00701     pfs.push_back(andr_th.getProof());
00702     pfs.push_back(a_th.getProof());
00703     pfs.push_back(l_th.getProof());
00704     pf = newPf("prop_andr_rf", exprs, pfs);
00705   }
00706 
00707   return newTheorem(andr_e[2].negate(), a, pf);
00708 }
00709 
00710 Theorem
00711 SearchEngineTheoremProducer::confAndrAT(const Theorem& andr_th,
00712                                         const Theorem& a_th,
00713                                         bool left,
00714                                         const Theorem& b_th) {
00715   const Expr& andr_e(andr_th.getExpr());
00716   if(CHECK_PROOFS) {
00717     CHECK_SOUND(andr_e.getKind() == AND_R && a_th.proves(andr_e[0]) &&
00718                 ((left && b_th.refutes(andr_e[1])) ||
00719                  (!left && b_th.refutes(andr_e[2]))),
00720                 "SearchEngineTheoremProducer::confAndrAT");
00721   }
00722 
00723   Assumptions a(andr_th, a_th);
00724   a.add(b_th);
00725   Proof pf;
00726 
00727   if(withProof()) {
00728     vector<Proof> pfs;
00729     vector<Expr> exprs;
00730     exprs.push_back(andr_th.getExpr());
00731     exprs.push_back(a_th.getExpr());
00732     exprs.push_back(b_th.getExpr());
00733     pfs.push_back(andr_th.getProof());
00734     pfs.push_back(a_th.getProof());
00735     pfs.push_back(b_th.getProof());
00736     // can we note which branch to take?
00737     pf = newPf("conf_andr_at", exprs, pfs);
00738   }
00739 
00740   return newTheorem(d_em->falseExpr(), a, pf);
00741 }
00742 
00743 Theorem
00744 SearchEngineTheoremProducer::confAndrAF(const Theorem& andr_th,
00745                                         const Theorem& a_th,
00746                                         const Theorem& l_th,
00747                                         const Theorem& r_th) {
00748   const Expr& andr_e(andr_th.getExpr());
00749   if(CHECK_PROOFS) {
00750     CHECK_SOUND(andr_e.getKind() == AND_R && a_th.refutes(andr_e[0]) &&
00751                 l_th.proves(andr_e[1]) && r_th.proves(andr_e[2]),
00752                 "SearchEngineTheoremProducer::confAndrAF");
00753   }
00754 
00755   Assumptions a;
00756   Proof pf;
00757   if(withAssumptions()) {
00758     a.add(andr_th);
00759     a.add(a_th);
00760     a.add(l_th);
00761     a.add(r_th);
00762   }
00763 
00764   if(withProof()) {
00765     vector<Proof> pfs;
00766     vector<Expr> exprs;
00767     exprs.push_back(andr_th.getExpr());
00768     exprs.push_back(a_th.getExpr());
00769     exprs.push_back(l_th.getExpr());
00770     exprs.push_back(r_th.getExpr());
00771     pfs.push_back(andr_th.getProof());
00772     pfs.push_back(a_th.getProof());
00773     pfs.push_back(l_th.getProof());
00774     pfs.push_back(r_th.getProof());
00775     pf = newPf("conf_andr_af", exprs, pfs);
00776   }
00777 
00778   return newTheorem(d_em->falseExpr(), a, pf);
00779 }
00780 
00781 Theorem
00782 SearchEngineTheoremProducer::propIffr(const Theorem& iffr_th,
00783                                       int p,
00784                                       const Theorem& a_th,
00785                                       const Theorem& b_th)
00786 {
00787   int a(-1), b(-1);
00788   if(CHECK_PROOFS)
00789     CHECK_SOUND(p == 0 || p == 1 || p == 2,
00790                 "SearchEngineTheoremProducer::propIffr: p="
00791                 +int2string(p));
00792   switch (p) {
00793   case 0: a = 1; b = 2; break;
00794   case 1: a = 0; b = 2; break;
00795   case 2: a = 0; b = 1; break;
00796   }
00797 
00798   const Expr& iffr_e(iffr_th.getExpr());
00799 
00800   bool v0 = a_th.proves(iffr_e[a]);
00801   bool v1 = b_th.proves(iffr_e[b]);
00802 
00803   if (CHECK_PROOFS) {
00804     CHECK_SOUND(iffr_e.getKind() == IFF_R &&
00805                 (v0 || a_th.refutes(iffr_e[a])) &&
00806                 (v1 || b_th.refutes(iffr_e[b])),
00807                 "SearchEngineTheoremProducer::propIffr");
00808   }
00809 
00810   Assumptions aa;
00811   Proof pf;
00812   if (withAssumptions()) {
00813     aa.add(iffr_th);
00814     aa.add(a_th);
00815     aa.add(b_th);
00816   }
00817 
00818   if (withProof()) {
00819     vector<Proof> pfs;
00820     vector<Expr> exprs;
00821     exprs.push_back(iffr_th.getExpr());
00822     exprs.push_back(a_th.getExpr());
00823     exprs.push_back(b_th.getExpr());
00824     pfs.push_back(iffr_th.getProof());
00825     pfs.push_back(a_th.getProof());
00826     pfs.push_back(b_th.getProof());
00827     pf = newPf("prop_iffr", exprs, pfs);
00828   }
00829 
00830   return newTheorem(v0 == v1 ? iffr_e[p] : iffr_e[p].negate(), aa, pf);
00831 }
00832 
00833 Theorem
00834 SearchEngineTheoremProducer::confIffr(const Theorem& iffr_th,
00835                                       const Theorem& i_th,
00836                                       const Theorem& l_th,
00837                                       const Theorem& r_th)
00838 {
00839   const Expr& iffr_e(iffr_th.getExpr());
00840 
00841   bool v0 = i_th.proves(iffr_e[0]);
00842   bool v1 = l_th.proves(iffr_e[1]);
00843   bool v2 = r_th.proves(iffr_e[2]);
00844 
00845   if (CHECK_PROOFS) {
00846     CHECK_SOUND(iffr_e.getKind() == IFF_R &&
00847                 (v0 || i_th.refutes(iffr_e[0])) &&
00848                 (v1 || l_th.refutes(iffr_e[1])) &&
00849                 (v2 || r_th.refutes(iffr_e[2])) &&
00850                 ((v0 && v1 != v2) || (!v0 && v1 == v2)),
00851                 "SearchEngineTheoremProducer::confIffr");
00852   }
00853 
00854   Assumptions a;
00855   Proof pf;
00856   if (withAssumptions()) {
00857     a.add(iffr_th);
00858     a.add(i_th);
00859     a.add(l_th);
00860     a.add(r_th);
00861   }
00862 
00863   if (withProof()) {
00864     vector<Proof> pfs;
00865     vector<Expr> exprs;
00866     exprs.push_back(iffr_th.getExpr());
00867     exprs.push_back(i_th.getExpr());
00868     exprs.push_back(l_th.getExpr());
00869     exprs.push_back(r_th.getExpr());
00870     pfs.push_back(iffr_th.getProof());
00871     pfs.push_back(i_th.getProof());
00872     pfs.push_back(l_th.getProof());
00873     pfs.push_back(r_th.getProof());
00874     pf = newPf("conf_iffr", exprs, pfs);
00875   }
00876 
00877   return newTheorem(d_em->falseExpr(), a, pf);
00878 }
00879 
00880 Theorem
00881 SearchEngineTheoremProducer::propIterIte(const Theorem& iter_th,
00882                                          bool left,
00883                                          const Theorem& if_th,
00884                                          const Theorem& then_th)
00885 {
00886   const Expr& iter_e(iter_th.getExpr());
00887 
00888   bool v0 = if_th.proves(iter_e[1]);
00889   bool v1 = then_th.proves(iter_e[left ? 2 : 3]);
00890 
00891   if (CHECK_PROOFS) {
00892     CHECK_SOUND(iter_e.getKind() == ITE_R &&
00893                 (v0 || if_th.refutes(iter_e[1])) &&
00894                 (v1 || then_th.refutes(iter_e[left ? 2 : 3])) &&
00895                 v0 == left,
00896                 "SearchEngineTheoremProducer::propIterIte");
00897   }
00898 
00899   Assumptions a;
00900   Proof pf;
00901   if (withAssumptions()) {
00902     a.add(iter_th);
00903     a.add(if_th);
00904     a.add(then_th);
00905   }
00906 
00907   if (withProof()) {
00908     vector<Proof> pfs;
00909     vector<Expr> exprs;
00910     exprs.push_back(iter_th.getExpr());
00911     exprs.push_back(if_th.getExpr());
00912     exprs.push_back(then_th.getExpr());
00913     pfs.push_back(iter_th.getProof());
00914     pfs.push_back(if_th.getProof());
00915     pfs.push_back(then_th.getProof());
00916     pf = newPf("prop_iter_ite", exprs, pfs);
00917   }
00918 
00919   return newTheorem(v1 ? iter_e[0] : iter_e[0].negate(), a, pf);
00920 }
00921 
00922 void
00923 SearchEngineTheoremProducer::propIterIfThen(const Theorem& iter_th,
00924                                             bool left,
00925                                             const Theorem& ite_th,
00926                                             const Theorem& then_th,
00927                                             Theorem* if_th,
00928                                             Theorem* else_th)
00929 {
00930   const Expr& iter_e(iter_th.getExpr());
00931 
00932   bool v0 = ite_th.proves(iter_e[0]);
00933   bool v1 = then_th.proves(iter_e[left ? 2 : 3]);
00934 
00935   if (CHECK_PROOFS) {
00936     CHECK_SOUND(iter_e.getKind() == ITE_R &&
00937                 (v0 || ite_th.refutes(iter_e[0])) &&
00938                 (v1 || then_th.refutes(iter_e[left ? 2 : 3])) &&
00939                 v0 != v1,
00940                 "SearchEngineTheoremProducer::propIterIfThen");
00941   }
00942 
00943   Assumptions a;
00944   Proof pf;
00945   if (withAssumptions()) {
00946     a.add(iter_th);
00947     a.add(ite_th);
00948     a.add(then_th);
00949   }
00950 
00951   if (withProof()) {
00952     vector<Proof> pfs;
00953     vector<Expr> exprs;
00954     exprs.push_back(iter_th.getExpr());
00955     exprs.push_back(ite_th.getExpr());
00956     exprs.push_back(then_th.getExpr());
00957     pfs.push_back(iter_th.getProof());
00958     pfs.push_back(ite_th.getProof());
00959     pfs.push_back(then_th.getExpr());
00960     pf = newPf("prop_iter_if_then", exprs, pfs);
00961   }
00962 
00963   if (if_th)
00964     *if_th = newTheorem(left ? iter_e[1].negate() : iter_e[1], a, pf);
00965   if (else_th)
00966     *else_th = newTheorem(v0 ? iter_e[left ? 3 : 2] : iter_e[left ? 3 : 2].negate(), a, pf);
00967 }
00968 
00969 Theorem
00970 SearchEngineTheoremProducer::propIterThen(const Theorem& iter_th,
00971                                           const Theorem& ite_th,
00972                                           const Theorem& if_th)
00973 {
00974   const Expr& iter_e(iter_th.getExpr());
00975 
00976   bool v0 = ite_th.proves(iter_e[0]);
00977   bool v1 = if_th.proves(iter_e[1]);
00978 
00979   if (CHECK_PROOFS) {
00980     CHECK_SOUND(iter_e.getKind() == ITE_R &&
00981                 (v0 || ite_th.refutes(iter_e[0])) &&
00982                 (v1 || if_th.refutes(iter_e[1])),
00983                 "SearchEngineTheoremProducer::propIterThen");
00984   }
00985 
00986   Assumptions a;
00987   Proof pf;
00988   if (withAssumptions()) {
00989     a.add(iter_th);
00990     a.add(ite_th);
00991     a.add(if_th);
00992   }
00993 
00994   if (withProof()) {
00995     vector<Proof> pfs;
00996     vector<Expr> exprs;
00997     exprs.push_back(iter_th.getExpr());
00998     exprs.push_back(ite_th.getExpr());
00999     exprs.push_back(if_th.getExpr());
01000     pfs.push_back(iter_th.getProof());
01001     pfs.push_back(ite_th.getProof());
01002     pfs.push_back(if_th.getExpr());
01003     pf = newPf("prop_iter_then", exprs, pfs);
01004   }
01005 
01006   return newTheorem(v1 ?
01007                     (v0 ? iter_e[2] : iter_e[2].negate()) :
01008                     (v0 ? iter_e[3] : iter_e[3].negate()), a, pf);
01009 }
01010 
01011 Theorem
01012 SearchEngineTheoremProducer::confIterThenElse(const Theorem& iter_th,
01013                                               const Theorem& ite_th,
01014                                               const Theorem& then_th,
01015                                               const Theorem& else_th)
01016 {
01017   const Expr& iter_e(iter_th.getExpr());
01018 
01019   bool v0 = ite_th.proves(iter_e[0]);
01020   bool v1 = then_th.proves(iter_e[2]);
01021   bool v2 = else_th.proves(iter_e[3]);
01022 
01023   if (CHECK_PROOFS) {
01024     CHECK_SOUND(iter_e.getKind() == ITE_R &&
01025                 (v0 || ite_th.refutes(iter_e[0])) &&
01026                 (v1 || then_th.refutes(iter_e[2])) &&
01027                 (v2 || else_th.refutes(iter_e[3])) &&
01028                 ((v0 && !v1 && !v2) || (!v0 && v1 && v2)),
01029                 "SearchEngineTheoremProducer::confIterThenElse");
01030   }
01031 
01032   Assumptions a;
01033   Proof pf;
01034   if (withAssumptions()) {
01035     a.add(iter_th);
01036     a.add(ite_th);
01037     a.add(then_th);
01038     a.add(else_th);
01039   }
01040 
01041   if (withProof()) {
01042     vector<Proof> pfs;
01043     vector<Expr> exprs;
01044     exprs.push_back(iter_th.getExpr());
01045     exprs.push_back(ite_th.getExpr());
01046     exprs.push_back(then_th.getExpr());
01047     exprs.push_back(else_th.getExpr());
01048     pfs.push_back(iter_th.getProof());
01049     pfs.push_back(ite_th.getProof());
01050     pfs.push_back(then_th.getExpr());
01051     pfs.push_back(else_th.getExpr());
01052     pf = newPf("conf_iter_then_else", exprs, pfs);
01053   }
01054 
01055   return newTheorem(d_em->falseExpr(), a, pf);
01056 }
01057 
01058 Theorem
01059 SearchEngineTheoremProducer::confIterIfThen(const Theorem& iter_th,
01060                                             bool left,
01061                                             const Theorem& ite_th,
01062                                             const Theorem& if_th,
01063                                             const Theorem& then_th)
01064 {
01065   const Expr& iter_e(iter_th.getExpr());
01066 
01067   bool v0 = ite_th.proves(iter_e[0]);
01068   bool v1 = if_th.proves(iter_e[1]);
01069   bool v2 = then_th.proves(iter_e[left ? 2 : 3]);
01070 
01071   if (CHECK_PROOFS) {
01072     CHECK_SOUND(iter_e.getKind() == ITE_R &&
01073                 (v0 || ite_th.refutes(iter_e[0])) &&
01074                 (v1 || if_th.refutes(iter_e[1])) &&
01075                 (v2 || then_th.refutes(iter_e[left ? 2 : 3])) &&
01076                 v1 == left && v0 != v2,
01077                 "SearchEngineTheoremProducer::confIterThenElse");
01078   }
01079 
01080   Assumptions a;
01081   Proof pf;
01082   if (withAssumptions()) {
01083     a.add(iter_th);
01084     a.add(ite_th);
01085     a.add(if_th);
01086     a.add(then_th);
01087   }
01088 
01089   if (withProof()) {
01090     vector<Proof> pfs;
01091     vector<Expr> exprs;
01092     exprs.push_back(iter_th.getExpr());
01093     exprs.push_back(ite_th.getExpr());
01094     exprs.push_back(if_th.getExpr());
01095     exprs.push_back(then_th.getExpr());
01096     pfs.push_back(iter_th.getProof());
01097     pfs.push_back(ite_th.getProof());
01098     pfs.push_back(if_th.getExpr());
01099     pfs.push_back(then_th.getExpr());
01100     pf = newPf("conf_iter_then_else", exprs, pfs);
01101   }
01102 
01103   return newTheorem(d_em->falseExpr(), a, pf);
01104 }
01105 
01106 // "Conflict" rule (all literals in a clause become FALSE)
01107 // { G_j |- !l_j, j in [1..n] } , G |- (OR l_1 ... l_n) ==> FALSE
01108 Theorem
01109 SearchEngineTheoremProducer::conflictRule(const std::vector<Theorem>& thms,
01110                                           const Theorem& clause) {
01111   Expr e(clause.getExpr());
01112   if(CHECK_PROOFS) {
01113     // Soundness check: first, check the form of the 'clause' theorem
01114     CHECK_SOUND(e.isOr(),
01115                 "SearchEngineTheoremProducer::unitProp: "
01116                 "bad theorem in clause = "+clause.toString());
01117     // Now, check correspondence of thms to the disjunction
01118     CHECK_SOUND(((int)thms.size()) == e.arity(),
01119                 "SearchEngineTheoremProducer::conflictRule: "
01120                 "wrong number of theorems"
01121                 "\n  thms.size = " + int2string(thms.size())
01122                 +"\n  clause.arity = " + int2string(e.arity()));
01123 
01124     for(unsigned j=0; j<thms.size(); j++) {
01125       Expr ej(e[j]), ek(thms[j].getExpr());
01126       CHECK_SOUND((ej.isNot() && ej[0] == ek) || (ek.isNot() && ej == ek[0]),
01127                   "SearchEngineTheoremProducer::conflictRule: "
01128                   "wrong theorem["+int2string(j)+"]"
01129                   "\n  thm = " + thms[j].toString() +
01130                   "\n  literal = " + e[j].toString() +
01131                   "\n  clause = " + clause.toString());
01132     }
01133   }
01134 
01135   Assumptions a(thms);
01136   a.add(clause);
01137   Proof pf;
01138   if(withProof()) {
01139     vector<Proof> pfs;
01140     vector<Expr> exprs;
01141     exprs.reserve(thms.size() + 1);
01142     pfs.reserve(thms.size()+1);
01143     const vector<Theorem>::const_iterator iend = thms.end();
01144     for(vector<Theorem>::const_iterator i=thms.begin(); i!=iend; ++i) {
01145       exprs.push_back(i->getExpr());
01146       pfs.push_back(i->getProof());
01147     }
01148     exprs.push_back(clause.getExpr());
01149     pfs.push_back(clause.getProof());
01150     pf = newPf("conflict", exprs, pfs);
01151   }
01152   return newTheorem(d_em->falseExpr(), a, pf);
01153 }
01154 
01155 
01156 ///////////////////////////////////////////////////////////////////////
01157 //// Conjunctive Normal Form (CNF) proof rules
01158 ///////////////////////////////////////////////////////////////////////
01159 Theorem
01160 SearchEngineTheoremProducer::andCNFRule(const Theorem& thm) {
01161   return opCNFRule(thm, AND, "and_cnf_rule");
01162 }
01163 
01164 Theorem
01165 SearchEngineTheoremProducer::orCNFRule(const Theorem& thm) {
01166   return opCNFRule(thm, OR, "or_cnf_rule");
01167 }
01168 
01169 Theorem
01170 SearchEngineTheoremProducer::impCNFRule(const Theorem& thm) {
01171   return opCNFRule(thm, IMPLIES, "implies_cnf_rule");
01172 }
01173 
01174 Theorem
01175 SearchEngineTheoremProducer::iffCNFRule(const Theorem& thm) {
01176   return opCNFRule(thm, IFF, "iff_cnf_rule");
01177 }
01178 
01179 Theorem
01180 SearchEngineTheoremProducer::iteCNFRule(const Theorem& thm) {
01181   return opCNFRule(thm, ITE, "ite_cnf_rule");
01182 }
01183 
01184 
01185 Theorem
01186 SearchEngineTheoremProducer::iteToClauses(const Theorem& ite) {
01187   const Expr& iteExpr = ite.getExpr();
01188 
01189   if(CHECK_PROOFS) {
01190     CHECK_SOUND(iteExpr.isITE() && iteExpr.getType().isBool(),
01191                 "SearchEngineTheoremProducer::iteToClauses("+iteExpr.toString()
01192                 +")\n Argument must be a Boolean ITE");
01193   }
01194   const Expr& cond = iteExpr[0];
01195   const Expr& t1 = iteExpr[1];
01196   const Expr& t2 = iteExpr[2];
01197 
01198   Proof pf;
01199   if(withProof())
01200     pf = newPf("ite_to_clauses", iteExpr, ite.getProof());
01201   return newTheorem((cond.negate() || t1) && (cond || t2), ite.getAssumptionsRef(), pf);
01202 }
01203 
01204 
01205 Theorem
01206 SearchEngineTheoremProducer::iffToClauses(const Theorem& iff) {
01207   if(CHECK_PROOFS) {
01208     CHECK_SOUND(iff.isRewrite() && iff.getLHS().getType().isBool(),
01209                 "SearchEngineTheoremProducer::iffToClauses("+iff.getExpr().toString()
01210                 +")\n Argument must be a Boolean IFF");
01211   }
01212   const Expr& t1 = iff.getLHS();
01213   const Expr& t2 = iff.getRHS();
01214 
01215   Proof pf;
01216   if(withProof())
01217     pf = newPf("iff_to_clauses", iff.getExpr(), iff.getProof());
01218   return newTheorem((t1.negate() || t2) && (t1 || t2.negate()), iff.getAssumptionsRef(), pf);
01219 }
01220 
01221 
01222 /////////////////////////////////////////////////////////////////////////
01223 //// helper functions for CNF (Conjunctive Normal Form) conversion
01224 /////////////////////////////////////////////////////////////////////////
01225 Theorem
01226 SearchEngineTheoremProducer::opCNFRule(const Theorem& thm, 
01227                                        int kind,
01228                                        const string& ruleName) {
01229   TRACE("mycnf", "opCNFRule["+d_em->getKindName(kind)+"](",
01230         thm.getExpr(), ") {");
01231   ExprMap<Expr> localCache;
01232   if(CHECK_PROOFS) {
01233     Expr phiIffVar = thm.getExpr();
01234     CHECK_SOUND(phiIffVar.isIff(),
01235                 "SearchEngineTheoremProducer::opCNFRule("
01236                 +d_em->getKindName(kind)+"): "
01237                 "input must be an IFF: thm = " + phiIffVar.toString());
01238     CHECK_SOUND(phiIffVar[0].getKind() == kind,
01239                 "SearchEngineTheoremProducer::opCNFRule("
01240                 +d_em->getKindName(kind)+"): "
01241                 "input phi has wrong kind: thm = " + phiIffVar.toString());
01242     CHECK_SOUND(phiIffVar[0] != phiIffVar[1],
01243                 "SearchEngineTheoremProducer::opCNFRule("
01244                 +d_em->getKindName(kind)+"): "
01245                 "wrong input thm = " + phiIffVar.toString());
01246     for(Expr::iterator it=phiIffVar[0].begin(), itend=phiIffVar[0].end();
01247         it!=itend;++it){
01248       CHECK_SOUND(phiIffVar[1] != *it,
01249                   "SearchEngineTheoremProducer::opCNFRule("
01250                   +d_em->getKindName(kind)+"): "
01251                   "wrong input thm = " + phiIffVar.toString());
01252     }
01253   }
01254   const Expr& phi = thm.getExpr()[0];
01255   const Expr& phiVar = thm.getExpr()[1];
01256 
01257   std::vector<Expr> boundVars;
01258   std::vector<Expr> boundVarsAndLiterals;
01259   std::vector<Expr> equivs;
01260   for(Expr::iterator i=phi.begin(), iend=phi.end(); i != iend; i++) {
01261     // First, strip the negation and check if the formula is atomic
01262     Expr tmp(*i);
01263     while(tmp.isNot())
01264       tmp = tmp[0];
01265 
01266     if(tmp.isPropAtom())
01267       boundVarsAndLiterals.push_back(*i); 
01268     else
01269       boundVarsAndLiterals.push_back(findInLocalCache(*i, localCache,
01270                                                       boundVars));
01271   }
01272   
01273   for(ExprMap<Expr>::iterator it=localCache.begin(), itend=localCache.end(); 
01274       it != itend; it++) {
01275     DebugAssert((*it).second.isIff(),
01276                 "SearchEngineTheoremProducer::opCNFRule: " +
01277                 (*it).second.toString());
01278     DebugAssert(!(*it).second[0].isPropLiteral() && 
01279                 (*it).second[1].isAbsLiteral(),
01280                 "SearchEngineTheoremProducer::opCNFRule: " +
01281                 (*it).second.toString());
01282     equivs.push_back((*it).second);
01283   }
01284   
01285   DebugAssert(boundVarsAndLiterals.size() == (unsigned)phi.arity(),
01286               "SearchEngineTheoremProducer::opCNFRule: "
01287               "wrong size of boundvars: phi = " + phi.toString());
01288   
01289   DebugAssert(boundVars.size() == equivs.size(),
01290               "SearchEngineTheoremProducer::opCNFRule: "
01291               "wrong size of boundvars: phi = " + phi.toString());
01292 
01293   Expr cnfInput = phi.arity() > 0 ? Expr(phi.getOp(), boundVarsAndLiterals) : phi;
01294   Expr  result = convertToCNF(phiVar, cnfInput);
01295   if(boundVars.size() > 0)
01296     result =
01297       d_em->newClosureExpr(EXISTS, boundVars, result.andExpr(andExpr(equivs)));
01298   
01299   Proof pf;
01300   if(withProof())
01301     pf = newPf(ruleName, thm.getExpr(), thm.getProof());
01302   Theorem res(newTheorem(result, thm.getAssumptionsRef(), pf));
01303   TRACE("mycnf", "opCNFRule["+d_em->getKindName(kind)+"] => ", res.getExpr(),
01304         " }");
01305   return res;
01306 }
01307 
01308 //! produces the CNF for the formula  v <==> phi 
01309 Expr SearchEngineTheoremProducer::convertToCNF(const Expr& v, const Expr & phi) {
01310   //we assume that v \iff phi. v is the newVar corresponding to phi
01311   
01312   Expr::iterator i = phi.begin(), iend = phi.end();
01313   std::vector<Expr> clauses;
01314   std::vector<Expr> lastClause;
01315   switch(phi.getKind()) {
01316   case AND: {
01317     const Expr& negV = v.negate();
01318     lastClause.push_back(v);
01319     for(;i!=iend; ++i) {
01320       lastClause.push_back(i->negate());
01321     }
01322     clauses.push_back(orExpr(lastClause));
01323   }
01324     break;
01325   case OR:{
01326     lastClause.push_back(v.negate());
01327     for(;i!=iend; ++i) {
01328       clauses.push_back(v.orExpr(i->negate()));
01329       lastClause.push_back(*i);
01330     }
01331     clauses.push_back(orExpr(lastClause));
01332   }
01333     break;
01334   case IFF: {
01335     const Expr& v1 = phi[0];
01336     const Expr& v2 = phi[1];
01337     Expr negV = v.negate();    
01338     Expr negv1 = v1.negate();
01339     Expr negv2 = v2.negate();
01340     clauses.push_back(Expr(OR, negV, negv1, v2));
01341     clauses.push_back(Expr(OR, negV, v1, negv2));
01342     clauses.push_back(Expr(OR, v, v1, v2));
01343     clauses.push_back(Expr(OR, v, negv1, negv2));
01344   } break;
01345   case IMPLIES:{
01346     const Expr& v1 = phi[0];
01347     const Expr& v2 = phi[1];
01348     Expr negV = v.negate();    
01349     Expr negv1 = v1.negate();
01350     Expr negv2 = v2.negate();
01351     clauses.push_back(Expr(OR, negV, negv1, v2));
01352     clauses.push_back(v.orExpr(v1));
01353     clauses.push_back(v.orExpr(negv2));
01354   }
01355     break;
01356   case ITE: {
01357     const Expr& v1 = phi[0];
01358     const Expr& v2 = phi[1];
01359     const Expr& v3 = phi[2];
01360     const Expr& negV = v.negate();
01361     const Expr& negv1 = v1.negate();
01362     const Expr& negv2 = v2.negate();
01363     const Expr& negv3 = v3.negate();
01364     clauses.push_back(Expr(OR, negV, negv1, v2));
01365     clauses.push_back(Expr(OR, negV, v1, v3));
01366     clauses.push_back(Expr(OR, v, negv1, negv2));
01367     clauses.push_back(Expr(OR, v, v1, negv3));
01368   }
01369     break;
01370   default:
01371     DebugAssert(false, "SearchEngineTheoremProducer::convertToCNF: "
01372                 "bad operator in phi = "+phi.toString());
01373     break;
01374   }
01375   return andExpr(clauses);
01376 }
01377 
01378 ///////////////////////////////////////////////////////////////////////
01379 // helper functions for CNF converters
01380 ///////////////////////////////////////////////////////////////////////
01381 
01382 Expr SearchEngineTheoremProducer::findInLocalCache(const Expr& i, 
01383                                                    ExprMap<Expr>& localCache,
01384                                                    vector<Expr>& boundVars) {
01385   TRACE("mycnf", "findInLocalCache(", i.toString(), ") { ");
01386   Expr boundVar;
01387   unsigned int negationDepth = 0;
01388   ExprMap<Expr>::iterator it;
01389  
01390   Expr phi = i;
01391   while(phi.isNot()) {
01392     phi = phi[0];
01393     negationDepth++;
01394   }
01395   
01396   it = localCache.find(phi);
01397   Expr v;
01398   if(it != localCache.end()) {
01399     v = ((*it).second)[1];
01400     IF_DEBUG(debugger.counter("CNF Local Cache Hits")++;)
01401   }
01402   else {
01403     v = d_em->newBoundVarExpr(i.getType());
01404     boundVars.push_back(v);
01405     localCache[phi] = phi.iffExpr(v);
01406   }
01407   if(negationDepth % 2 != 0)
01408     v = !v;
01409   TRACE("mycnf", "findInLocalCache => ", v, " }");
01410   return v;
01411 }
01412 
01413 
01414 
01415 // for LFSC proof style, by yeting
01416 
01417 
01418 // theorem for minisat generated proofs,  by yeting
01419 Theorem SearchEngineTheoremProducer::satProof(const Expr& queryExpr, const Proof& satProof) {
01420   Proof pf;
01421   if(withProof())
01422     pf = newPf("minisat_proof", queryExpr, satProof);
01423 
01424   if ((d_tm->getFlags()["lfsc-mode"]).getInt()!= 0)
01425   {
01426     // UNCOMMENT THIS FOR LFSC
01427 
01428     if(!lfsc_called){
01429       int lfscm = (d_tm->getFlags()["lfsc-mode"]).getInt();
01430       std::vector<Expr> assumps;
01431       search_engine->getUserAssumptions(assumps);
01432 
01433       Expr pf_expr =  pf.getExpr()[2] ;
01434       if( lfscm == -1 ){
01435         cout << "CVC3 Proof: ";
01436         cout << pf.getExpr() << endl;
01437       }else{
01438         LFSCPrinter* lfsc_printer = new LFSCPrinter(pf_expr, queryExpr, assumps, lfscm, d_commonRules);
01439         lfsc_printer->print_LFSC(pf_expr);
01440         lfsc_called = true;
01441         exit( 0 );
01442       }
01443     }
01444 
01445   }
01446 
01447   return newTheorem(queryExpr, Assumptions::emptyAssump() , pf);
01448 }
01449 
01450 
01451 //  LocalWords:  clc