/*****************************************************************************/ /*! * \file search_simple.cpp * * Author: Clark Barrett * * Created: Sat Mar 29 21:59:36 2003 * *
* * License to use, copy, modify, sell and/or distribute this software * and its documentation for any purpose is hereby granted without * royalty, subject to the terms and conditions defined in the \ref * LICENSE file provided with this distribution. * *
* */ /*****************************************************************************/ #include "search_simple.h" #include "theory_core.h" #include "typecheck_exception.h" #include "search_rules.h" #include "decision_engine_dfs.h" //#include "decision_engine_caching.h" //#include "decision_engine_mbtf.h" #include "expr_transform.h" #include "command_line_flags.h" using namespace std; using namespace CVC3; QueryResult SearchSimple::checkValidRec(Theorem& thm) { if (d_core->outOfResources()) return ABORT; TRACE_MSG("search", "checkValidRec() {"); if (d_core->inconsistent()) { TRACE("search", "checkValidRec => ", d_core->inconsistentThm(), " (context inconsistent) }"); d_decisionEngine->goalSatisfied(); thm = d_core->inconsistentThm(); return UNSATISFIABLE; } Theorem e = d_goal.get(); bool workingOnGoal = true; if (d_goal.get().getExpr().isTrue()) { e = d_nonLiterals.get(); workingOnGoal = false; } Theorem simp = simplify(e); Expr rhs = simp.getExpr(); if (rhs.hasFind()) { simp = d_commonRules->iffMP(simp, d_core->find(rhs)); rhs = simp.getExpr(); } if (workingOnGoal) d_goal.set(simp); else d_nonLiterals.set(simp); if (rhs.isFalse()) { TRACE("search", "checkValidRec => ", simp, " (rhs=false) }"); d_decisionEngine->goalSatisfied(); thm = simp; return UNSATISFIABLE; } else if (rhs.isTrue()) { if (workingOnGoal || !d_core->checkSATCore()) { return checkValidRec(thm); } TRACE("search", "checkValidRec => ", "Null (true)", "}"); thm = Theorem(); return SATISFIABLE; } Expr splitter = d_decisionEngine->findSplitter(rhs); DebugAssert(!splitter.isNull(), "Expected splitter"); d_decisionEngine->pushDecision(splitter); QueryResult qres = checkValidRec(thm); if (qres == UNSATISFIABLE) { d_decisionEngine->popDecision(); d_decisionEngine->pushDecision(splitter, false); Theorem thm2; qres = checkValidRec(thm2); if (qres == UNSATISFIABLE) { d_decisionEngine->popDecision(); thm = d_rules->caseSplit(splitter, thm, thm2); return qres; } thm = thm2; return qres; } return qres; } SearchSimple::SearchSimple(TheoryCore* core) : SearchImplBase(core), d_name("simple"), d_goal(core->getCM()->getCurrentContext()), d_nonLiterals(core->getCM()->getCurrentContext()), d_simplifiedThm(core->getCM()->getCurrentContext()) { // if (core->getFlags()["de"].getString() == "caching") // d_decisionEngine = new DecisionEngineCaching(core, this); // else if (core->getFlags()["de"].getString() == "mbtf") // d_decisionEngine = new DecisionEngineMBTF(core, this); // else d_decisionEngine = new DecisionEngineDFS(core, this); d_goal.set(d_commonRules->trueTheorem()); d_nonLiterals.set(d_commonRules->trueTheorem()); } SearchSimple::~SearchSimple() { delete d_decisionEngine; } QueryResult SearchSimple::checkValidMain(const Expr& e2) { Theorem thm; QueryResult qres = checkValidRec(thm); if (qres == SATISFIABLE && d_core->incomplete()) qres = UNKNOWN; if (qres == SATISFIABLE) { DebugAssert(d_goal.get().getExpr().isTrue(), "checkValid: Expected true goal"); vector a; d_goal.get().getLeafAssumptions(a); d_lastCounterExample.clear(); for (vector::iterator i=a.begin(), iend=a.end(); i != iend; ++i) { d_lastCounterExample[*i] = true; } } else if (qres != UNSATISFIABLE) return qres; processResult(thm, e2); if (qres == UNSATISFIABLE) { TRACE_MSG("search terse", "checkValid => true}"); TRACE("search", "checkValid => true; theorem = ", d_lastValid, "}"); Theorem e_iff_e2(d_commonRules->iffContrapositive(d_simplifiedThm)); d_lastValid = d_commonRules->iffMP(d_lastValid, d_commonRules->symmetryRule(e_iff_e2)); d_core->getCM()->pop(); } else { TRACE_MSG("search terse", "checkValid => false}"); TRACE_MSG("search", "checkValid => false; }"); } return qres; } QueryResult SearchSimple::checkValidInternal(const Expr& e) { DebugAssert(d_goal.get().getExpr().isTrue(),"checkValid: Expected true goal"); DebugAssert(d_nonLiterals.get().getExpr().isTrue(),"checkValid: Expected true nonLiterals"); TRACE("search", "checkValid(", e, ") {"); TRACE_MSG("search terse", "checkValid() {"); if (!e.getType().isBool()) { throw TypecheckException ("checking validity of a non-boolean expression:\n\n " + e.toString() + "\n\nwhich has the following type:\n\n " + e.getType().toString()); } // A successful query should leave the context unchanged d_core->getCM()->push(); d_bottomScope = scopeLevel(); d_simplifiedThm.set(d_core->getExprTrans()->preprocess(e.negate())); TRACE("search", "checkValid: simplifiedThm = ", d_simplifiedThm, ""); const Expr& not_e2 = d_simplifiedThm.get().getRHS(); Expr e2 = not_e2.negate(); // Assert not_e2 if it's not already asserted TRACE_MSG("search terse", "checkValid: Asserting !e: "); TRACE("search", "checkValid: Asserting !e: ", not_e2, ""); Theorem not_e2_thm; if(d_assumptions.count(not_e2) == 0) { not_e2_thm = newUserAssumption(not_e2); } else { not_e2_thm = d_assumptions[not_e2]; } d_core->addFact(not_e2_thm); d_goal.set(not_e2_thm); return checkValidMain(e2); } QueryResult SearchSimple::restartInternal(const Expr& e) { TRACE("search", "restart(", e, ") {"); TRACE_MSG("search terse", "restart() {"); if (!e.getType().isBool()) { throw TypecheckException ("argument to restart is a non-boolean expression:\n\n " + e.toString() + "\n\nwhich has the following type:\n\n " + e.getType().toString()); } if (d_bottomScope == 0) { throw Exception("Call to restart with no current query"); } d_core->getCM()->popto(d_bottomScope); Expr e2 = d_simplifiedThm.get().getRHS().negate(); TRACE_MSG("search terse", "restart: Asserting e: "); TRACE("search", "restart: Asserting e: ", e, ""); if(d_assumptions.count(e) == 0) { d_core->addFact(newUserAssumption(e)); } return checkValidMain(e2); } void SearchSimple::addNonLiteralFact(const Theorem& thm) { d_nonLiterals.set(d_commonRules->andIntro(d_nonLiterals.get(), thm)); }