solver.cpp
Go to the documentation of this file.
00001 // 
00002 // Copyright (c) 2006-2012, Benjamin Kaufmann
00003 // 
00004 // This file is part of Clasp. See http://www.cs.uni-potsdam.de/clasp/ 
00005 // 
00006 // Clasp is free software; you can redistribute it and/or modify
00007 // it under the terms of the GNU General Public License as published by
00008 // the Free Software Foundation; either version 2 of the License, or
00009 // (at your option) any later version.
00010 // 
00011 // Clasp is distributed in the hope that it will be useful,
00012 // but WITHOUT ANY WARRANTY; without even the implied warranty of
00013 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00014 // GNU General Public License for more details.
00015 // 
00016 // You should have received a copy of the GNU General Public License
00017 // along with Clasp; if not, write to the Free Software
00018 // Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
00019 //
00020 #include <clasp/solver.h>
00021 #include <clasp/clause.h>
00022 
00023 #ifdef _MSC_VER
00024 #pragma warning (disable : 4996) // 'std::copy': Function call with parameters that may be unsafe
00025 #endif
00026 namespace Clasp { 
00027 
00028 DecisionHeuristic::~DecisionHeuristic() {}
00030 // SelectFirst selection strategy
00032 // selects the first free literal
00033 Literal SelectFirst::doSelect(Solver& s) {
00034         for (Var i = 1; i <= s.numVars(); ++i) {
00035                 if (s.value(i) == value_free) {
00036                         return selectLiteral(s, i, 0);
00037                 }
00038         }
00039         assert(!"SelectFirst::doSelect() - precondition violated!\n");
00040         return Literal();
00041 }
00043 // Post propagator list
00045 static PostPropagator* sent_list;
00046 Solver::PPList::PPList() : list(0) { enable(); }
00047 Solver::PPList::~PPList() {
00048         for (PostPropagator* r = head(); r;) {
00049                 PostPropagator* t = r;
00050                 r = r->next;
00051                 t->destroy();
00052         }
00053 }
00054 
00055 void Solver::PPList::disable() { act = &sent_list; }
00056 void Solver::PPList::enable()  { act = &list; }
00057 
00058 void Solver::PPList::add(PostPropagator* p, uint32 prio) {
00059         assert(p && p->next == 0);
00060         for (PostPropagator** r = &list, *x;; r = &x->next) {
00061                 if ((x = *r) == 0 || prio <= x->priority()) {
00062                         p->next = x;
00063                         *r      = p;
00064                         break;
00065                 }
00066         }
00067 }
00068 
00069 void Solver::PPList::remove(PostPropagator* p) {
00070         assert(p);
00071         for (PostPropagator** r = &list, *x; *r; r = &x->next) {
00072                 if ((x = *r) == p) {
00073                         *r      = x->next;
00074                         p->next = 0;
00075                         break;
00076                 }
00077         }
00078 }
00079 
00080 bool Solver::PPList::propagate(Solver& s, PostPropagator* x) const {
00081         for (PostPropagator** r = act, *t; *r != x; ) {
00082                 t = *r;
00083                 if (!t->propagateFixpoint(s, x)) { return false; }
00084                 assert(s.queueSize() == 0);
00085                 if (t == *r) { r = &t->next; }
00086                 // else: t was removed during propagate
00087         }
00088         return true;
00089 }
00090 
00091 void Solver::PPList::simplify(Solver& s, bool shuf) {
00092         for (PostPropagator* r = active(); r;) {
00093                 PostPropagator* t = r;
00094                 r = r->next;
00095                 if (t->simplify(s, shuf)) {
00096                         remove(t);
00097                 }
00098         }
00099 }
00100 
00101 void Solver::PPList::cancel()           const { for (PostPropagator* r = active(); r; r = r->next) { r->reset(); } }
00102 bool Solver::PPList::isModel(Solver& s) const {
00103         if (s.hasConflict()) { return false; }
00104         for (PostPropagator* r = active(); r; r = r->next) {
00105                 if (!r->isModel(s)){ return false; }
00106         }
00107         return !s.enumerationConstraint() || s.enumerationConstraint()->valid(s);
00108 }
00110 // Solver: Construction/Destruction/Setup
00112 Solver::Solver(SharedContext* ctx, uint32 id) 
00113         : shared_(ctx)
00114         , ccMin_(0)
00115         , smallAlloc_(new SmallClauseAlloc)
00116         , undoHead_(0)
00117         , enum_(0)
00118         , memUse_(0)
00119         , ccInfo_(Constraint_t::learnt_conflict)
00120         , lbdTime_(0)
00121         , dbIdx_(0)
00122         , lastSimp_(0)
00123         , shufSimp_(0)
00124         , initPost_(0){
00125         Var sentVar = assign_.addVar();
00126         assign_.setValue(sentVar, value_true);
00127         markSeen(sentVar);
00128         strategy.id = id;
00129 }
00130 
00131 Solver::~Solver() {
00132         freeMem();
00133 }
00134 
00135 void Solver::freeMem() {
00136         std::for_each( constraints_.begin(), constraints_.end(), DestroyObject());
00137         std::for_each( learnts_.begin(), learnts_.end(), DestroyObject() );
00138         constraints_.clear();
00139         learnts_.clear();
00140         setEnumerationConstraint(0);
00141         heuristic_.reset(0);
00142         PodVector<WatchList>::destruct(watches_);
00143         // free undo lists
00144         // first those still in use
00145         for (DecisionLevels::size_type i = 0; i != levels_.size(); ++i) {
00146                 delete levels_[i].undo;
00147         }
00148         // then those in the free list
00149         for (ConstraintDB* x = undoHead_; x; ) {
00150                 ConstraintDB* t = x;
00151                 x = (ConstraintDB*)x->front();
00152                 delete t;
00153         }
00154         delete smallAlloc_;
00155         delete ccMin_;
00156         smallAlloc_ = 0;
00157         ccMin_      = 0;
00158         memUse_     = 0;
00159 }
00160 
00161 SatPreprocessor*    Solver::satPrepro()     const { return shared_->satPrepro.get(); }
00162 const SolverParams& Solver::configuration() const { return shared_->configuration()->solver(id()); }
00163 const SolveParams&  Solver::searchConfig()  const { return shared_->configuration()->search(id()); }
00164 
00165 void Solver::reset() {
00166         SharedContext* myCtx = shared_;
00167         uint32         myId  = strategy.id;
00168         this->~Solver();
00169         new (this) Solver(myCtx, myId);
00170 }
00171 
00172 void Solver::startInit(uint32 numConsGuess) {
00173         assert(numVars() <= shared_->numVars());
00174         assign_.resize(shared_->numVars() + 1);
00175         watches_.resize(assign_.numVars()<<1);
00176         // pre-allocate some memory
00177         assign_.trail.reserve(numVars());
00178         constraints_.reserve(numConsGuess/2);
00179         levels_.reserve(25);
00180         if (smallAlloc_ == 0) { 
00181                 smallAlloc_ = new SmallClauseAlloc(); 
00182         }
00183         if (undoHead_ == 0)   {
00184                 for (uint32 i = 0; i != 25; ++i) { 
00185                         undoFree(new ConstraintDB(10)); 
00186                 }
00187         }
00188         const SolverParams& params = configuration();
00189         if (strategy.loadCfg == 1) {
00190                 uint32 id       = this->id();
00191                 uint32 hId      = strategy.heuReserved;
00192                 strategy        = params;
00193                 strategy.id     = id; // keep id
00194                 strategy.loadCfg= 0;  // strategy is now "up to date"
00195                 if      (!params.ccMinRec)  { delete ccMin_; ccMin_ = 0; }
00196                 else if (!ccMin_)           { ccMin_ = new CCMinRecursive; }
00197                 if (id == params.id || !shared_->seedSolvers()) {
00198                         rng.srand(params.seed);
00199                 }
00200                 else {
00201                         RNG x(14182940); for (uint32 i = 0; i != id; ++i) { x.rand(); }
00202                         rng.srand(x.seed());
00203                 }
00204                 if (hId != params.heuId) { // heuristic has changed
00205                         heuristic_.reset(0);
00206                 }
00207         }
00208         if (heuristic_.get() == 0) {
00209                 heuristic_.reset(shared_->configuration()->heuristic(id()));
00210                 strategy.heuReserved = params.heuId;
00211         }
00212         if (!popRootLevel(rootLevel())) { return; }
00213         if (!learnts_.empty()) {
00214                 if      (params.dropLearnt > 1) { reduceLearnts(1.0f); }
00215                 else if (params.dropLearnt ==1) {
00216                         Activity hint(0, Activity::MAX_LBD);
00217                         for (uint32 i = 0, end = learnts_.size(); i != end; ++i) {
00218                                 static_cast<LearntConstraint*>(learnts_[i])->resetActivity(hint);
00219                         }
00220                 }
00221         }
00222         post_.disable(); // disable post propagators during setup
00223         initPost_ = 0;   // defer calls to PostPropagator::init()
00224         heuristic_->startInit(*this);
00225 }
00226 
00227 bool Solver::cloneDB(const ConstraintDB& db) {
00228         assert(!hasConflict());
00229         while (dbIdx_ < (uint32)db.size() && !hasConflict()) {
00230                 if (Constraint* c = db[dbIdx_++]->cloneAttach(*this)) {
00231                         constraints_.push_back(c);
00232                 }
00233         }
00234         return !hasConflict();
00235 }
00236 bool Solver::preparePost() {
00237         if (hasConflict()) { return false; }
00238         if (initPost_ == 0){
00239                 initPost_ = 1;
00240                 for (PostPropagator* x = post_.head(), *t; (t = x) != 0; ) {
00241                         x = x->next;
00242                         if (!t->init(*this)) { return false; }
00243                 }
00244         }
00245         return shared_->configuration()->addPost(*this);
00246 }
00247 PostPropagator* Solver::getPost(uint32 prio) const {
00248         for (PostPropagator* x = post_.head(); x; x = x->next) {
00249                 uint32 xp = x->priority();
00250                 if (xp >= prio) { return xp == prio ? x : 0; }
00251         }
00252         return 0;
00253 }
00254 bool Solver::endInit() {
00255         if (hasConflict()) { return false; }
00256         heuristic_->endInit(*this);
00257         if (strategy.signFix) {
00258                 for (Var v = 1; v <= numVars(); ++v) {
00259                         Literal x = DecisionHeuristic::selectLiteral(*this, v, 0);
00260                         setPref(v, ValueSet::user_value, x.sign() ? value_false : value_true);
00261                 }
00262         }
00263         post_.enable(); // enable all post propagators
00264         return propagate() && simplify();
00265 }
00266 
00267 void Solver::add(Constraint* c) {
00268         constraints_.push_back(c);
00269 }
00270 bool Solver::add(const ClauseRep& c, bool isNew) {
00271         typedef ShortImplicationsGraph::ImpType ImpType;
00272         if (c.prep == 0) {
00273                 return ClauseCreator::create(*this, c, ClauseCreator::clause_force_simplify).ok();
00274         }
00275         int added = 0;
00276         if (c.size > 1) {
00277                 if (allowImplicit(c)) { added = shared_->addImp(static_cast<ImpType>(c.size), c.lits, c.info.type()); }
00278                 else                  { return ClauseCreator::create(*this, c, ClauseCreator::clause_explicit).ok(); }
00279         }
00280         else {
00281                 Literal u = c.size ? c.lits[0] : negLit(0);
00282                 uint32  ts= trail().size();
00283                 force(u);
00284                 added     = int(ts != trail().size());
00285         }
00286         if (added > 0 && isNew && c.info.learnt()) {
00287                 stats.addLearnt(c.size, c.info.type());
00288                 distribute(c.lits, c.size, c.info);
00289         }
00290         return !hasConflict();
00291 }
00292 uint32 Solver::receive(SharedLiterals** out, uint32 maxOut) const {
00293         if (shared_->distributor.get()) {
00294                 return shared_->distributor->receive(*this, out, maxOut);
00295         }
00296         return 0;
00297 }
00298 SharedLiterals* Solver::distribute(const Literal* lits, uint32 size, const ClauseInfo& extra) {
00299         if (shared_->distributor.get() && !extra.aux() && (size <= 3 || shared_->distributor->isCandidate(size, extra.lbd(), extra.type()))) {
00300                 uint32 initialRefs = shared_->concurrency() - (size <= Clause::MAX_SHORT_LEN || !shared_->physicalShare(extra.type()));
00301                 SharedLiterals* x  = SharedLiterals::newShareable(lits, size, extra.type(), initialRefs);
00302                 shared_->distributor->publish(*this, x);
00303                 stats.addDistributed(extra.lbd(), extra.type());
00304                 return initialRefs == shared_->concurrency() ? x : 0;
00305         }
00306         return 0;
00307 }
00308 void Solver::setEnumerationConstraint(Constraint* c) {
00309         if (enum_) enum_->destroy(this, true);
00310         enum_ = c;
00311 }
00312 
00313 uint32 Solver::numConstraints() const {
00314         return static_cast<uint32>(constraints_.size())
00315                 + (shared_ ? shared_->numBinary()+shared_->numTernary() : 0);
00316 }
00317 
00318 Var Solver::pushAuxVar() {
00319         Var aux = assign_.addVar();
00320         setPref(aux, ValueSet::def_value, value_false);
00321         watches_.insert(watches_.end(), 2, WatchList()); 
00322         if (heuristic_.get()) { heuristic_->updateVar(*this, aux, 1); }
00323         return aux;
00324 }
00325 void Solver::popAuxVar(uint32 num) {
00326         num = numVars() >= shared_->numVars() ? std::min(numVars() - shared_->numVars(), num) : 0;
00327         if (!num) { return; }
00328         // 1. find first dl containing one of the aux vars
00329         Literal aux = posLit(assign_.numVars() - num);
00330         uint32  dl  = decisionLevel() + 1;
00331         for (ImpliedList::iterator it = impliedLits_.begin(); it != impliedLits_.end(); ++it) {
00332                 if (!(it->lit < aux)) { dl = std::min(dl, it->level); }
00333         }
00334         for (Var v = aux.var(), end = aux.var()+num; v != end; ++v) {
00335                 if (value(v) != value_free){ dl = std::min(dl, level(v)); }
00336         }
00337         // 2. remove aux vars from assignment
00338         if (dl > rootLevel()) {
00339                 if (backtrackLevel() >= dl) { setBacktrackLevel(dl-1); }
00340                 undoUntil(dl-1, true);
00341         }
00342         else {
00343                 popRootLevel((rootLevel() - dl) + 1);
00344                 if (dl == 0) { // top-level has aux vars - cleanup manually
00345                         uint32 j = shared_->numUnary(), units = assign_.units();
00346                         for (uint32 i = j, end = assign_.trail.size(); i != end; ++i) {
00347                                 if (assign_.trail[i] < aux) { assign_.trail[j++] = assign_.trail[i]; }
00348                                 else                        {
00349                                         units         -= (i < units);
00350                                         assign_.front -= (i < assign_.front);
00351                                         lastSimp_     -= (i < lastSimp_);
00352                                 }
00353                         }
00354                         shrinkVecTo(assign_.trail, j);
00355                         assign_.setUnits(units);
00356                 }
00357         }
00358         // 3. remove constraints over aux
00359         ConstraintDB::size_type i, j, end = learnts_.size();
00360         LitVec cc;
00361         for (i = j = 0; i != end; ++i) {
00362                 cc.clear();
00363                 if (ClauseHead* c = static_cast<LearntConstraint*>(learnts_[i])->clause()) { c->toLits(cc); }
00364                 if (std::find_if(cc.begin(), cc.end(), std::not1(std::bind2nd(std::less<Literal>(), aux))) == cc.end()) {
00365                         learnts_[j++] = learnts_[i];
00366                 }
00367                 else { learnts_[i]->destroy(this, true); }
00368         }
00369         learnts_.erase(learnts_.begin()+j, learnts_.end());
00370         // 4. remove aux vars and their watches
00371         assign_.resize(assign_.numVars()-num);
00372         for (uint32 n = num; n--;) { 
00373                 watches_.back().clear(true);
00374                 watches_.pop_back();
00375                 watches_.back().clear(true);
00376                 watches_.pop_back();
00377         }
00378         if (!validVar(tag_.var())) { tag_ = posLit(0); }
00379         heuristic_->updateVar(*this, aux.var(), num);
00380 }
00381 
00382 bool Solver::pushRoot(const LitVec& path) {
00383         // make sure we are on the current root level
00384         if (!popRootLevel(0) || !simplify() || !propagate()) { return false; }
00385         // push path
00386         stats.addPath(path.size());
00387         for (LitVec::const_iterator it = path.begin(), end = path.end(); it != end; ++it) {
00388                 if (!pushRoot(*it)) { return false; }
00389         }
00390         ccInfo_.setActivity(1);
00391         return true;
00392 }
00393 
00394 bool Solver::pushRoot(Literal x) {
00395         if (hasConflict())                 { return false; }
00396         if (decisionLevel()!= rootLevel()) { popRootLevel();  }
00397         if (queueSize() && !propagate())   { return false;    }
00398         if (value(x.var()) != value_free)  { return isTrue(x);}
00399         assume(x); --stats.choices;
00400         pushRootLevel();
00401         return propagate();
00402 }
00403 
00404 bool Solver::popRootLevel(uint32 i, LitVec* popped, bool aux)  {
00405         clearStopConflict();
00406         uint32 newRoot = levels_.root - std::min(i, rootLevel());
00407         if (popped && newRoot < rootLevel()) {
00408                 for (uint32 i = newRoot+1; i <= rootLevel(); ++i) {
00409                         Literal x = decision(i);
00410                         if (aux || !auxVar(x.var())) { popped->push_back(x); }
00411                 }
00412         }
00413         levels_.root       = newRoot;
00414         levels_.backtrack  = rootLevel();
00415         impliedLits_.front = 0;
00416         bool tagActive     = isTrue(tagLiteral());
00417         // go back to new root level and re-assert still implied literals
00418         undoUntil(rootLevel(), true);
00419         if (tagActive && !isTrue(tagLiteral())) {
00420                 removeConditional();
00421         }
00422         return !hasConflict();
00423 }
00424 
00425 bool Solver::clearAssumptions()  {
00426         return popRootLevel(rootLevel())
00427                 && simplify();
00428 }
00429 
00430 void Solver::clearStopConflict() {
00431         if (hasStopConflict()) {
00432                 levels_.root = conflict_[1].asUint();
00433                 assign_.front= conflict_[2].asUint();
00434                 conflict_.clear();
00435         }
00436 }
00437 
00438 void Solver::setStopConflict() {
00439         if (!hasConflict()) {
00440                 // we use the nogood {FALSE} to represent the unrecoverable conflict -
00441                 // note that {FALSE} can otherwise never be a violated nogood because
00442                 // TRUE is always true in every solver
00443                 conflict_.push_back(negLit(0));
00444                 // remember the current root-level
00445                 conflict_.push_back(Literal::fromRep(rootLevel()));
00446                 // remember the current propagation queue
00447                 conflict_.push_back(Literal::fromRep(assign_.front));
00448         }
00449         // artificially increase root level -
00450         // this way, the solver is prevented from resolving the conflict
00451         pushRootLevel(decisionLevel());
00452 }
00453 
00454 void Solver::copyGuidingPath(LitVec& gpOut) {
00455         uint32 aux = rootLevel()+1;
00456         gpOut.clear();
00457         for (uint32 i = 1, end = rootLevel()+1; i != end; ++i) {
00458                 Literal x = decision(i);
00459                 if      (!auxVar(x.var())) { gpOut.push_back(x); }
00460                 else if (i < aux)          { aux = i; }
00461         }
00462         for (ImpliedList::iterator it = impliedLits_.begin(); it != impliedLits_.end(); ++it) {
00463                 if (it->level <= rootLevel() && (it->ante.ante().isNull() || it->level < aux) && !auxVar(it->lit.var())) {
00464                         gpOut.push_back(it->lit);
00465                 }
00466         }
00467 }
00468 bool Solver::splittable() const {
00469         if (decisionLevel() == rootLevel() || frozenLevel(rootLevel()+1)) { return false; }
00470         if (numAuxVars()) { // check if gp would contain solver local aux var
00471                 uint32 minAux = rootLevel() + 2;
00472                 for (uint32 i = 1; i != minAux; ++i) { 
00473                         if (auxVar(decision(i).var()) && decision(i) != tag_) { return false; } 
00474                 }
00475                 for (ImpliedList::iterator it = impliedLits_.begin(); it != impliedLits_.end(); ++it) {
00476                         if (it->ante.ante().isNull() && it->level < minAux && auxVar(it->lit.var()) && it->lit != tag_) { return false; }
00477                 }
00478         }
00479         return true;
00480 }
00481 bool Solver::split(LitVec& out) {
00482         if (!splittable()) { return false; }
00483         copyGuidingPath(out);
00484         pushRootLevel();
00485         out.push_back(~decision(rootLevel()));
00486         stats.addSplit();
00487         return true;
00488 }
00490 // Solver: Watch management
00492 uint32 Solver::numWatches(Literal p) const {
00493         assert( validVar(p.var()) );
00494         if (!validWatch(p)) return 0;
00495         return static_cast<uint32>(watches_[p.index()].size()) 
00496                 + shared_->shortImplications().numEdges(p);
00497 }
00498         
00499 bool Solver::hasWatch(Literal p, Constraint* c) const {
00500         if (!validWatch(p)) return false;
00501         const WatchList& pList = watches_[p.index()];
00502         return std::find_if(pList.right_begin(), pList.right_end(), GenericWatch::EqConstraint(c)) != pList.right_end();
00503 }
00504 
00505 bool Solver::hasWatch(Literal p, ClauseHead* h) const {
00506         if (!validWatch(p)) return false;
00507         const WatchList& pList = watches_[p.index()];
00508         return std::find_if(pList.left_begin(), pList.left_end(), ClauseWatch::EqHead(h)) != pList.left_end();
00509 }
00510 
00511 GenericWatch* Solver::getWatch(Literal p, Constraint* c) const {
00512         if (!validWatch(p)) return 0;
00513         const WatchList& pList = watches_[p.index()];
00514         WatchList::const_right_iterator it = std::find_if(pList.right_begin(), pList.right_end(), GenericWatch::EqConstraint(c));
00515         return it != pList.right_end()
00516                 ? &const_cast<GenericWatch&>(*it)
00517                 : 0;
00518 }
00519 
00520 void Solver::removeWatch(const Literal& p, Constraint* c) {
00521         assert(validWatch(p));
00522         WatchList& pList = watches_[p.index()];
00523         pList.erase_right(std::find_if(pList.right_begin(), pList.right_end(), GenericWatch::EqConstraint(c)));
00524 }
00525 
00526 void Solver::removeWatch(const Literal& p, ClauseHead* h) {
00527         assert(validWatch(p));
00528         WatchList& pList = watches_[p.index()];
00529         pList.erase_left(std::find_if(pList.left_begin(), pList.left_end(), ClauseWatch::EqHead(h)));
00530 }
00531 
00532 bool Solver::removeUndoWatch(uint32 dl, Constraint* c) {
00533         assert(dl != 0 && dl <= decisionLevel() );
00534         if (levels_[dl-1].undo) {
00535                 ConstraintDB& uList = *levels_[dl-1].undo;
00536                 ConstraintDB::iterator it = std::find(uList.begin(), uList.end(), c);
00537                 if (it != uList.end()) {
00538                         *it = uList.back();
00539                         uList.pop_back();
00540                         return true;
00541                 }
00542         }
00543         return false;
00544 }
00545 
00547 // Solver: Basic DPLL-functions
00549 
00550 // removes all satisfied binary and ternary clauses as well
00551 // as all constraints for which Constraint::simplify returned true.
00552 bool Solver::simplify() {
00553         if (decisionLevel() != 0) return true;
00554         if (hasConflict())        return false;
00555         if (lastSimp_ != (uint32)assign_.trail.size()) {
00556                 uint32 old = lastSimp_;
00557                 if (!simplifySAT()) { return false; }
00558                 assert(lastSimp_ == (uint32)assign_.trail.size());
00559                 heuristic_->simplify(*this, old);
00560         }
00561         if (shufSimp_) { simplifySAT(); }
00562         return true;
00563 }
00564 Var  Solver::pushTagVar(bool pushToRoot) {
00565         if (isSentinel(tag_)) { tag_ = posLit(pushAuxVar()); }
00566         if (pushToRoot)       { pushRoot(tag_); }
00567         return tag_.var();
00568 }
00569 void Solver::removeConditional() { 
00570         Literal p = ~tagLiteral();
00571         if (!isSentinel(p)) {
00572                 ConstraintDB::size_type i, j, end = learnts_.size();
00573                 for (i = j = 0; i != end; ++i) {
00574                         ClauseHead* c = static_cast<LearntConstraint*>(learnts_[i])->clause();
00575                         if (!c || !c->tagged()) {
00576                                 learnts_[j++] = learnts_[i];
00577                         }
00578                         else {
00579                                 c->destroy(this, true);
00580                         }
00581                 }
00582                 learnts_.erase(learnts_.begin()+j, learnts_.end());
00583         }
00584 }
00585 
00586 void Solver::strengthenConditional() { 
00587         Literal p = ~tagLiteral();
00588         if (!isSentinel(p)) {
00589                 ConstraintDB::size_type i, j, end = learnts_.size();
00590                 for (i = j = 0; i != end; ++i) {
00591                         ClauseHead* c = static_cast<LearntConstraint*>(learnts_[i])->clause();
00592                         if (!c || !c->tagged() || !c->strengthen(*this, p, true).second) {
00593                                 learnts_[j++] = learnts_[i];
00594                         }
00595                         else {
00596                                 assert((decisionLevel() == rootLevel() || !c->locked(*this)) && "Solver::strengthenConditional(): must not remove locked constraint!");
00597                                 c->destroy(this, false);
00598                         }
00599                 }
00600                 learnts_.erase(learnts_.begin()+j, learnts_.end());
00601         }
00602 }
00603 
00604 bool Solver::simplifySAT() {
00605         if (queueSize() > 0 && !propagate()) {
00606                 return false;
00607         }
00608         assert(assign_.qEmpty());
00609         assign_.front = lastSimp_;
00610         lastSimp_     = (uint32)assign_.trail.size();
00611         for (Literal p; !assign_.qEmpty(); ) {
00612                 p = assign_.qPop();
00613                 releaseVec(watches_[p.index()]);
00614                 releaseVec(watches_[(~p).index()]);
00615                 shared_->simplifyShort(*this, p);
00616         }
00617         bool shuffle = shufSimp_ != 0;
00618         shufSimp_    = 0;
00619         if (shuffle) {
00620                 std::random_shuffle(constraints_.begin(), constraints_.end(), rng);
00621                 std::random_shuffle(learnts_.begin(), learnts_.end(), rng);
00622         }
00623         if (this == shared_->master()) { shared_->simplify(shuffle); }
00624         else                           { simplifyDB(*this, constraints_, shuffle); }
00625         simplifyDB(*this, learnts_, shuffle);
00626         post_.simplify(*this, shuffle);
00627         if (enum_ && enum_->simplify(*this, shuffle)) {
00628                 enum_->destroy(this, false);
00629                 enum_ = 0;
00630         }
00631         return true;
00632 }
00633 
00634 void Solver::setConflict(Literal p, const Antecedent& a, uint32 data) {
00635         ++stats.conflicts;
00636         conflict_.push_back(~p);
00637         if (strategy.search != SolverStrategies::no_learning && !a.isNull()) {
00638                 if (data == UINT32_MAX) {
00639                         a.reason(*this, p, conflict_);
00640                 }
00641                 else {
00642                         // temporarily replace old data with new data
00643                         uint32 saved = assign_.data(p.var());
00644                         assign_.setData(p.var(), data);
00645                         // extract conflict using new data
00646                         a.reason(*this, p, conflict_);
00647                         // restore old data
00648                         assign_.setData(p.var(), saved);
00649                 }
00650         }
00651 }
00652 
00653 bool Solver::assume(const Literal& p) {
00654         if (value(p.var()) == value_free) {
00655                 assert(decisionLevel() != assign_.maxLevel());
00656                 ++stats.choices;
00657                 levels_.push_back(DLevel(numAssignedVars(), 0));
00658                 return assign_.assign(p, decisionLevel(), Antecedent());
00659         }
00660         return isTrue(p);
00661 }
00662 
00663 bool Solver::propagate() {
00664         if (unitPropagate() && post_.propagate(*this, 0)) {
00665                 assert(queueSize() == 0);
00666                 return true;
00667         }
00668         cancelPropagation();
00669         return false;
00670 }
00671 
00672 Constraint::PropResult ClauseHead::propagate(Solver& s, Literal p, uint32&) {
00673         Literal* head = head_;
00674         uint32 wLit   = (head[1] == ~p); // pos of false watched literal
00675         if (s.isTrue(head[1-wLit])) {
00676                 return Constraint::PropResult(true, true);
00677         }
00678         else if (!s.isFalse(head[2])) {
00679                 assert(!isSentinel(head[2]) && "Invalid ClauseHead!");
00680                 head[wLit] = head[2];
00681                 head[2]    = ~p;
00682                 s.addWatch(~head[wLit], ClauseWatch(this));
00683                 return Constraint::PropResult(true, false);
00684         }
00685         else if (updateWatch(s, wLit)) {
00686                 assert(!s.isFalse(head_[wLit]));
00687                 s.addWatch(~head[wLit], ClauseWatch(this));
00688                 return Constraint::PropResult(true, false);
00689         }       
00690         return PropResult(s.force(head_[1^wLit], this), true);
00691 }
00692 
00693 bool Solver::unitPropagate() {
00694         assert(!hasConflict());
00695         Literal p, q, r;
00696         uint32 idx, ignore, DL = decisionLevel();
00697         const ShortImplicationsGraph& btig = shared_->shortImplications();
00698         const uint32 maxIdx = btig.size();
00699         while ( !assign_.qEmpty() ) {
00700                 p             = assign_.qPop();
00701                 idx           = p.index();
00702                 WatchList& wl = watches_[idx];
00703                 // first: short clause BCP
00704                 if (idx < maxIdx && !btig.propagate(*this, p)) {
00705                         return false;
00706                 }
00707                 // second: clause BCP
00708                 if (wl.left_size() != 0) {
00709                         WatchList::left_iterator it, end, j = wl.left_begin(); 
00710                         Constraint::PropResult res;
00711                         for (it = wl.left_begin(), end = wl.left_end();  it != end;  ) {
00712                                 ClauseWatch& w = *it++;
00713                                 res = w.head->ClauseHead::propagate(*this, p, ignore);
00714                                 if (res.keepWatch) {
00715                                         *j++ = w;
00716                                 }
00717                                 if (!res.ok) {
00718                                         wl.shrink_left(std::copy(it, end, j));
00719                                         return false;
00720                                 }
00721                         }
00722                         wl.shrink_left(j);
00723                 }
00724                 // third: general constraint BCP
00725                 if (wl.right_size() != 0) {
00726                         WatchList::right_iterator it, end, j = wl.right_begin(); 
00727                         Constraint::PropResult res;
00728                         for (it = wl.right_begin(), end = wl.right_end(); it != end; ) {
00729                                 GenericWatch& w = *it++;
00730                                 res = w.propagate(*this, p);
00731                                 if (res.keepWatch) {
00732                                         *j++ = w;
00733                                 }
00734                                 if (!res.ok) {
00735                                         wl.shrink_right(std::copy(it, end, j));
00736                                         return false;
00737                                 }
00738                         }
00739                         wl.shrink_right(j);
00740                 }
00741         }
00742         return DL || assign_.markUnits();
00743 }
00744 
00745 bool Solver::test(Literal p, PostPropagator* c) {
00746         assert(value(p.var()) == value_free && !hasConflict());
00747         assume(p); --stats.choices;
00748         uint32 pLevel = decisionLevel();
00749         freezeLevel(pLevel); // can't split-off this level
00750         if (propagateUntil(c)) {
00751                 assert(decisionLevel() == pLevel && "Invalid PostPropagators");
00752                 if (c) c->undoLevel(*this);
00753                 undoUntil(pLevel-1);
00754                 return true;
00755         }
00756         assert(decisionLevel() == pLevel && "Invalid PostPropagators");
00757         unfreezeLevel(pLevel);
00758         cancelPropagation();
00759         return false;
00760 }
00761 
00762 bool Solver::resolveConflict() {
00763         assert(hasConflict());
00764         if (decisionLevel() > rootLevel()) {
00765                 if (decisionLevel() != backtrackLevel() && strategy.search != SolverStrategies::no_learning) {
00766                         uint32 uipLevel = analyzeConflict();
00767                         stats.updateJumps(decisionLevel(), uipLevel, backtrackLevel(), ccInfo_.lbd());
00768                         undoUntil( uipLevel );
00769                         return ClauseCreator::create(*this, cc_, ClauseCreator::clause_no_prepare, ccInfo_);
00770                 }
00771                 else {
00772                         return backtrack();
00773                 }
00774         }
00775         return false;
00776 }
00777 
00778 bool Solver::backtrack() {
00779         Literal lastChoiceInverted;
00780         do {
00781                 if (decisionLevel() == rootLevel()) {
00782                         setStopConflict();
00783                         return false;
00784                 }
00785                 lastChoiceInverted = ~decision(decisionLevel());
00786                 levels_.backtrack = decisionLevel() - 1;
00787                 undoUntil(backtrackLevel(), true);
00788         } while (hasConflict() || !force(lastChoiceInverted, 0));
00789         // remember flipped literal for copyGuidingPath()
00790         impliedLits_.add(decisionLevel(), ImpliedLiteral(lastChoiceInverted, decisionLevel(), 0));
00791         return true;
00792 }
00793 
00794 bool ImpliedList::assign(Solver& s) {
00795         assert(front <= lits.size());
00796         bool ok             = !s.hasConflict();
00797         const uint32 DL     = s.decisionLevel();
00798         VecType::iterator j = lits.begin() + front;
00799         for (VecType::iterator it = j, end = lits.end(); it != end; ++it) {
00800                 if(it->level <= DL) {
00801                         ok = ok && s.force(it->lit, it->ante.ante(), it->ante.data());
00802                         if (it->level < DL || it->ante.ante().isNull()) { *j++ = *it; }
00803                 }
00804         }
00805         lits.erase(j, lits.end());
00806         level = DL * uint32(!lits.empty());
00807         front = level > s.rootLevel() ? front  : lits.size();
00808         return ok;
00809 }
00810 
00811 void Solver::undoUntil(uint32 level) {
00812         assert(backtrackLevel() >= rootLevel());
00813         level      = std::max( level, backtrackLevel() );
00814         if (level >= decisionLevel()) return;
00815         uint32 num = decisionLevel() - level;
00816         bool sp    = strategy.saveProgress > 0 && ((uint32)strategy.saveProgress) <= num;
00817         bool ok    = conflict_.empty() && levels_.back().freeze == 0;
00818         conflict_.clear();
00819         heuristic_->undoUntil( *this, levels_[level].trailPos);
00820         undoLevel(sp && ok);
00821         while (--num) { undoLevel(sp); }
00822         assert(level == decisionLevel());
00823 }
00824 uint32 Solver::undoUntil(uint32 level, bool popBt) {
00825         if (popBt && backtrackLevel() > level && !varInfo(decision(backtrackLevel()).var()).project()) {
00826                 setBacktrackLevel(level);
00827         }
00828         undoUntil(level);
00829         if (impliedLits_.active(level = decisionLevel())) {
00830                 impliedLits_.assign(*this);
00831         }
00832         return level;
00833 }
00834 
00835 uint32 Solver::estimateBCP(const Literal& p, int rd) const {
00836         if (value(p.var()) != value_free) return 0;
00837         LitVec::size_type first = assign_.assigned();
00838         LitVec::size_type i     = first;
00839         Solver& self            = const_cast<Solver&>(*this);
00840         self.assign_.setValue(p.var(), trueValue(p));
00841         self.assign_.trail.push_back(p);
00842         const ShortImplicationsGraph& btig = shared_->shortImplications();
00843         const uint32 maxIdx = btig.size();
00844         do {
00845                 Literal x = assign_.trail[i++];  
00846                 if (x.index() < maxIdx && !btig.propagateBin(self.assign_, x, 0)) {
00847                         break;
00848                 }
00849         } while (i < assign_.assigned() && rd-- != 0);
00850         i = assign_.assigned()-first;
00851         while (self.assign_.assigned() != first) {
00852                 self.assign_.undoLast();
00853         }
00854         return (uint32)i;
00855 }
00856 
00857 uint32 Solver::inDegree(WeightLitVec& out) {
00858         if (decisionLevel() == 0) { return 1; }
00859         assert(!hasConflict());
00860         out.reserve((numAssignedVars()-levelStart(1))/10);
00861         uint32 maxIn  = 1;
00862         uint32 i      = assign_.trail.size(), stop = levelStart(1);
00863         for (Antecedent xAnte; i-- != stop; ) {
00864                 Literal x     = assign_.trail[i];
00865                 uint32  xLev  = assign_.level(x.var());
00866                 xAnte         = assign_.reason(x.var());
00867                 uint32  xIn   = 0;
00868                 if (!xAnte.isNull() && xAnte.type() != Antecedent::binary_constraint) {
00869                         xAnte.reason(*this, x, conflict_);
00870                         for (LitVec::const_iterator it = conflict_.begin(); it != conflict_.end(); ++it) {
00871                                 xIn += level(it->var()) != xLev;
00872                         }
00873                         if (xIn) {
00874                                 out.push_back(WeightLiteral(x, xIn));
00875                                 maxIn     = std::max(xIn, maxIn);
00876                         }
00877                         conflict_.clear();
00878                 }
00879         }
00880         assert(!hasConflict());
00881         return maxIn;
00882 }
00884 // Solver: Private helper functions
00886 Solver::ConstraintDB* Solver::allocUndo(Constraint* c) {
00887         if (undoHead_ == 0) {
00888                 return new ConstraintDB(1, c);
00889         }
00890         assert(undoHead_->size() == 1);
00891         ConstraintDB* r = undoHead_;
00892         undoHead_ = (ConstraintDB*)undoHead_->front();
00893         r->clear();
00894         r->push_back(c);
00895         return r;
00896 }
00897 void Solver::undoFree(ConstraintDB* x) {
00898         // maintain a single-linked list of undo lists
00899         x->clear();
00900         x->push_back((Constraint*)undoHead_);
00901         undoHead_ = x;
00902 }
00903 // removes the current decision level
00904 void Solver::undoLevel(bool sp) {
00905         assert(decisionLevel() != 0 && levels_.back().trailPos != assign_.trail.size() && "Decision Level must not be empty");
00906         assign_.undoTrail(levels_.back().trailPos, sp);
00907         if (levels_.back().undo) {
00908                 const ConstraintDB& undoList = *levels_.back().undo;
00909                 for (ConstraintDB::size_type i = 0, end = undoList.size(); i != end; ++i) {
00910                         undoList[i]->undoLevel(*this);
00911                 }
00912                 undoFree(levels_.back().undo);
00913         }
00914         levels_.pop_back();
00915 }
00916 
00917 inline ClauseHead* clause(const Antecedent& ante) {
00918         return ante.isNull() || ante.type() != Antecedent::generic_constraint ? 0 : ante.constraint()->clause();
00919 }
00920 
00921 // computes the First-UIP clause and stores it in cc_, where cc_[0] is the asserting literal (inverted UIP)
00922 // and cc_[1] is a literal from the asserting level (if > 0)
00923 // RETURN: asserting level of the derived conflict clause
00924 uint32 Solver::analyzeConflict() {
00925         // must be called here, because we unassign vars during analyzeConflict
00926         heuristic_->undoUntil( *this, levels_.back().trailPos );
00927         uint32 onLevel  = 0;        // number of literals from the current DL in resolvent
00928         uint32 resSize  = 0;        // size of current resolvent
00929         Literal p;                  // literal to be resolved out next
00930         cc_.assign(1, p);           // will later be replaced with asserting literal
00931         Antecedent lhs, rhs, last;  // resolve operands
00932         const bool doOtfs = strategy.otfs > 0;
00933         for (bumpAct_.clear();;) {
00934                 uint32 lhsSize = resSize;
00935                 uint32 rhsSize = 0;
00936                 heuristic_->updateReason(*this, conflict_, p);
00937                 for (LitVec::size_type i = 0; i != conflict_.size(); ++i) {
00938                         Literal& q = conflict_[i];
00939                         uint32 cl  = level(q.var());
00940                         rhsSize   += (cl != 0);
00941                         if (!seen(q.var())) {
00942                                 ++resSize;
00943                                 assert(isTrue(q) && "Invalid literal in reason set!");
00944                                 assert(cl > 0 && "Top-Level implication not marked!");
00945                                 markSeen(q.var());
00946                                 if (cl == decisionLevel()) {
00947                                         ++onLevel;
00948                                 }
00949                                 else {
00950                                         cc_.push_back(~q);
00951                                         markLevel(cl);
00952                                 }
00953                         }
00954                 }
00955                 if (resSize != lhsSize) { lhs = 0; }
00956                 if (rhsSize != resSize) { rhs = 0; }
00957                 if (doOtfs && (!rhs.isNull() || !lhs.isNull())) {
00958                         // resolvent subsumes rhs and possibly also lhs
00959                         otfs(lhs, rhs, p, onLevel == 1);
00960                 }
00961                 assert(onLevel > 0 && "CONFLICT MUST BE ANALYZED ON CONFLICT LEVEL!");
00962                 // search for the last assigned literal that needs to be analyzed...
00963                 while (!seen(assign_.last().var())) {
00964                         assign_.undoLast();
00965                 }
00966                 p   = assign_.last();
00967                 rhs = reason(p);
00968                 clearSeen(p.var());
00969                 if (--onLevel == 0) { 
00970                         break; 
00971                 }
00972                 --resSize; // p will be resolved out next
00973                 last = rhs;
00974                 reason(p, conflict_);
00975         }
00976         cc_[0] = ~p; // store the 1-UIP
00977         assert(decisionLevel() == level(cc_[0].var()));
00978         ClauseHead* lastRes = 0;
00979         if (strategy.otfs > 1 || !lhs.isNull()) {
00980                 if (!lhs.isNull()) { 
00981                         lastRes = clause(lhs);
00982                 }
00983                 else if (cc_.size() <= (conflict_.size()+1)) {
00984                         lastRes = clause(last);
00985                 }
00986         }
00987         if (strategy.bumpVarAct && reason(p).learnt()) {
00988                 bumpAct_.push_back(WeightLiteral(p, static_cast<LearntConstraint*>(reason(p).constraint())->activity().lbd()));
00989         }
00990         return simplifyConflictClause(cc_, ccInfo_, lastRes);
00991 }
00992 
00993 void Solver::otfs(Antecedent& lhs, const Antecedent& rhs, Literal p, bool final) {
00994         ClauseHead* cLhs = clause(lhs), *cRhs = clause(rhs);
00995         ClauseHead::BoolPair x;
00996         if (cLhs) {
00997                 x = cLhs->strengthen(*this, ~p, !final);
00998                 if (!x.first || x.second) {
00999                         cLhs = !x.first ? 0 : otfsRemove(cLhs, 0);
01000                 }
01001         }
01002         lhs = cLhs;
01003         if (cRhs) {
01004                 x = cRhs->strengthen(*this, p, !final);
01005                 if (!x.first || (x.second && otfsRemove(cRhs, 0) == 0)) {
01006                         if (x.first && reason(p) == cRhs) { setReason(p, 0); }
01007                         cRhs = 0;
01008                 }
01009                 if (cLhs && cRhs) {
01010                         // lhs and rhs are now equal - only one of them is needed
01011                         if (!cLhs->learnt()) {
01012                                 std::swap(cLhs, cRhs);
01013                         }
01014                         otfsRemove(cLhs, 0);
01015                 }
01016                 lhs = cRhs;
01017         }
01018 }
01019 
01020 ClauseHead* Solver::otfsRemove(ClauseHead* c, const LitVec* newC) {
01021         bool remStatic = !newC || (newC->size() <= 3 && shared_->allowImplicit(Constraint_t::learnt_conflict));
01022         if (c->learnt() || remStatic) {
01023                 ConstraintDB& db = (c->learnt() ? learnts_ : constraints_);
01024                 ConstraintDB::iterator it;
01025                 if ((it = std::find(db.begin(), db.end(), c)) != db.end()) {
01026                         if (this == shared_->master() && &db == &constraints_) {
01027                                 shared_->removeConstraint(static_cast<uint32>(it - db.begin()), true);
01028                         }
01029                         else {
01030                                 db.erase(it);
01031                                 c->destroy(this, true);
01032                         }
01033                         c = 0;
01034                 }
01035         }
01036         return c;
01037 }
01038 
01039 // minimizes the conflict clause in cc w.r.t selected strategies.
01040 // PRE:
01041 //  - cc is a valid conflict clause and cc[0] is the UIP-literal
01042 //  - all literals in cc except cc[0] are marked
01043 //  - all decision levels of literals in cc are marked
01044 //  - rhs is 0 or a clause that might be subsumed by cc
01045 // RETURN: finalizeConflictClause(cc, info)
01046 uint32 Solver::simplifyConflictClause(LitVec& cc, ClauseInfo& info, ClauseHead* rhs) {
01047         // 1. remove redundant literals from conflict clause
01048         temp_.clear();
01049         uint32 onAssert = ccMinimize(cc, temp_, strategy.ccMinAntes, ccMin_);
01050         uint32 jl       = cc.size() > 1 ? level(cc[1].var()) : 0;
01051         // clear seen flags of removed literals - keep levels marked
01052         for (LitVec::size_type x = 0, stop = temp_.size(); x != stop; ++x) {
01053                 clearSeen(temp_[x].var());
01054         }
01055         // 2. check for inverse arcs
01056         if (onAssert == 1 && strategy.reverseArcs > 0) {
01057                 uint32 maxN = (uint32)strategy.reverseArcs;
01058                 if      (maxN > 2) maxN = UINT32_MAX;
01059                 else if (maxN > 1) maxN = static_cast<uint32>(cc.size() / 2);
01060                 markSeen(cc[0].var());
01061                 Antecedent ante = ccHasReverseArc(cc[1], jl, maxN);
01062                 if (!ante.isNull()) {
01063                         // resolve with inverse arc
01064                         conflict_.clear();
01065                         ante.reason(*this, ~cc[1], conflict_);
01066                         ccResolve(cc, 1, conflict_);
01067                 }
01068                 clearSeen(cc[0].var());
01069         }
01070         // 3. check if final clause subsumes rhs
01071         if (rhs) {
01072                 conflict_.clear();
01073                 rhs->toLits(conflict_);
01074                 uint32 open   = (uint32)cc.size();
01075                 markSeen(cc[0].var());
01076                 for (LitVec::const_iterator it = conflict_.begin(), end = conflict_.end(); it != end && open; ++it) {
01077                         // NOTE: at this point the DB might not be fully simplified,
01078                         //       e.g. because of mt or lookahead, hence we must explicitly
01079                         //       check for literals assigned on DL 0
01080                         open -= level(it->var()) > 0 && seen(it->var());
01081                 }
01082                 rhs = open ? 0 : otfsRemove(rhs, &cc); 
01083                 if (rhs) { // rhs is subsumed by cc but could not be removed.
01084                         // TODO: we could reuse rhs instead of learning cc
01085                         //       but this would complicate the calling code.
01086                         ClauseHead::BoolPair r(true, false);
01087                         if (cc_.size() < conflict_.size()) {
01088                                 //     For now, we only try to strengthen rhs.
01089                                 for (LitVec::const_iterator it = conflict_.begin(), end = conflict_.end(); it != end && r.first; ++it) {
01090                                         if (!seen(it->var()) || level(it->var()) == 0) {
01091                                                 r = rhs->strengthen(*this, *it, false);
01092                                         }
01093                                 }
01094                                 if (!r.first) { rhs = 0; }
01095                         }
01096                 }
01097                 clearSeen(cc[0].var());
01098         }
01099         // 4. finalize
01100         uint32 repMode = cc.size() < std::max(strategy.compress, decisionLevel()+1) ? 0 : strategy.ccRepMode;
01101         jl = finalizeConflictClause(cc, info, repMode);
01102         // 5. bump vars implied by learnt constraints with small lbd 
01103         if (!bumpAct_.empty()) {
01104                 WeightLitVec::iterator j = bumpAct_.begin();
01105                 weight_t newLbd = info.lbd();
01106                 for (WeightLitVec::iterator it = bumpAct_.begin(), end = bumpAct_.end(); it != end; ++it) {
01107                         if (it->second < newLbd) {
01108                                 it->second = 1 + (it->second <= 2); 
01109                                 *j++ = *it;     
01110                         }
01111                 }
01112                 bumpAct_.erase(j, bumpAct_.end());
01113                 heuristic_->bump(*this, bumpAct_, 1.0);
01114         }
01115         bumpAct_.clear();
01116         // 6. clear level flags of redundant literals
01117         for (LitVec::size_type x = 0, stop = temp_.size(); x != stop; ++x) {
01118                 unmarkLevel(level(temp_[x].var()));
01119         }
01120         return jl;
01121 }
01122 
01123 // conflict clause minimization
01124 // PRE: 
01125 //  - cc is an asserting clause and cc[0] is the asserting literal
01126 //  - all literals in cc are marked as seen
01127 //  -  if ccMin != 0, all decision levels of literals in cc are marked
01128 // POST:
01129 //  - redundant literals were added to removed
01130 //  - if (cc.size() > 1): cc[1] is a literal from the asserting level
01131 // RETURN
01132 //  - the number of literals from the asserting level
01133 uint32 Solver::ccMinimize(LitVec& cc, LitVec& removed, uint32 antes, CCMinRecursive* ccMin) {
01134         if (ccMin) { ccMin->init(numVars()+1); }
01135         // skip the asserting literal
01136         LitVec::size_type j = 1;
01137         uint32 assertLevel  = 0;
01138         uint32 assertPos    = 1;
01139         uint32 onAssert     = 0;
01140         uint32 varLevel     = 0;
01141         for (LitVec::size_type i = 1; i != cc.size(); ++i) { 
01142                 if (antes == 0 || !ccRemovable(~cc[i], antes-1, ccMin)) {
01143                         if ( (varLevel = level(cc[i].var())) > assertLevel ) {
01144                                 assertLevel = varLevel;
01145                                 assertPos   = static_cast<uint32>(j);
01146                                 onAssert    = 0;
01147                         }
01148                         onAssert += (varLevel == assertLevel);
01149                         cc[j++] = cc[i];
01150                 }
01151                 else { 
01152                         removed.push_back(cc[i]);
01153                 }
01154         }
01155         cc.erase(cc.begin()+j, cc.end());
01156         if (assertPos != 1) {
01157                 std::swap(cc[1], cc[assertPos]);
01158         }
01159         if (ccMin) { ccMin->clear(); }
01160         return onAssert;
01161 }
01162 
01163 // returns true if p is redundant in current conflict clause
01164 bool Solver::ccRemovable(Literal p, uint32 antes, CCMinRecursive* ccMin) {
01165         const Antecedent& ante = reason(p);
01166         if (ante.isNull() || !(antes <= (uint32)ante.type())) {
01167                 return false;
01168         }
01169         if (!ccMin) { return ante.minimize(*this, p, 0); }
01170         // recursive minimization
01171         LitVec& dfsStack = ccMin->dfsStack;
01172         assert(dfsStack.empty());
01173         CCMinRecursive::State dfsState = CCMinRecursive::state_removable;
01174         p.clearWatch();
01175         dfsStack.push_back(p);
01176         for (Literal x;; ) {
01177                 x = dfsStack.back();
01178                 dfsStack.pop_back();
01179                 assert(!seen(x.var()) || x == p);
01180                 if (x.watched()) {
01181                         if (x == p) return dfsState == CCMinRecursive::state_removable;
01182                         ccMin->markVisited(x, dfsState);
01183                 }
01184                 else if (dfsState != CCMinRecursive::state_poison) {
01185                         CCMinRecursive::State temp = ccMin->state(x);
01186                         if (temp == CCMinRecursive::state_open) {
01187                                 assert(value(x.var()) != value_free && hasLevel(level(x.var())));
01188                                 x.watch();
01189                                 dfsStack.push_back(x);
01190                                 const Antecedent& ante = reason(x);
01191                                 if (ante.isNull() || !(antes <= (uint32)ante.type()) || !ante.minimize(*this, x, ccMin)) {
01192                                         dfsState = CCMinRecursive::state_poison;
01193                                 }
01194                         }
01195                         else if (temp == CCMinRecursive::state_poison) {
01196                                 dfsState = temp;
01197                         }
01198                 }
01199         }
01200 }
01201 
01202 // checks whether there is a valid "inverse arc" for the given literal p that can be used
01203 // to resolve p out of the current conflict clause
01204 // PRE: 
01205 //  - all literals in the current conflict clause are marked
01206 //  - p is a literal of the current conflict clause and level(p) == maxLevel
01207 // RETURN
01208 //  - An antecedent that is an "inverse arc" for p or null if no such antecedent exists.
01209 Antecedent Solver::ccHasReverseArc(Literal p, uint32 maxLevel, uint32 maxNew) {
01210         assert(seen(p.var()) && isFalse(p) && level(p.var()) == maxLevel);
01211         const ShortImplicationsGraph& btig = shared_->shortImplications();
01212         Antecedent ante;
01213         if (p.index() < btig.size() && btig.reverseArc(*this, p, maxLevel, ante)) { return ante; }
01214         WatchList& wl   = watches_[p.index()];
01215         WatchList::left_iterator it, end; 
01216         for (it = wl.left_begin(), end = wl.left_end();  it != end;  ++it) {
01217                 if (it->head->isReverseReason(*this, ~p, maxLevel, maxNew)) {
01218                         return it->head;
01219                 }
01220         }
01221         return ante;
01222 }
01223 
01224 // removes cc[pos] by resolving cc with reason
01225 void Solver::ccResolve(LitVec& cc, uint32 pos, const LitVec& reason) {
01226         heuristic_->updateReason(*this, reason, cc[pos]);
01227         Literal x;
01228         for (LitVec::size_type i = 0; i != reason.size(); ++i) {
01229                 x = reason[i];
01230                 assert(isTrue(x));
01231                 if (!seen(x.var())) {
01232                         markLevel(level(x.var()));
01233                         cc.push_back(~x);
01234                 }
01235         }
01236         clearSeen(cc[pos].var());
01237         unmarkLevel(level(cc[pos].var()));
01238         cc[pos] = cc.back();
01239         cc.pop_back();
01240 }
01241 
01242 // computes asserting level and lbd of cc and clears flags.
01243 // POST:
01244 //  - literals and decision levels in cc are no longer marked
01245 //  - if cc.size() > 1: cc[1] is a literal from the asserting level
01246 // RETURN: asserting level of conflict clause.
01247 uint32 Solver::finalizeConflictClause(LitVec& cc, ClauseInfo& info, uint32 ccRepMode) {
01248         // 2. clear flags and compute lbd
01249         uint32  lbd         = 1;
01250         uint32  onRoot      = 0;
01251         uint32  varLevel    = 0;
01252         uint32  assertLevel = 0;
01253         uint32  assertPos   = 1;
01254         uint32  maxVar      = cc[0].var();
01255         Literal tagLit      = ~tagLiteral();
01256         bool    tagged      = false;
01257         for (LitVec::size_type i = 1; i != cc.size(); ++i) {
01258                 Var v = cc[i].var();
01259                 clearSeen(v);
01260                 if (cc[i] == tagLit) { tagged = true; }
01261                 if (v > maxVar)      { maxVar = v;    }
01262                 if ( (varLevel = level(v)) > assertLevel ) {
01263                         assertLevel = varLevel;
01264                         assertPos   = static_cast<uint32>(i);
01265                 }
01266                 if (hasLevel(varLevel)) {
01267                         unmarkLevel(varLevel);
01268                         lbd += (varLevel > rootLevel()) || (++onRoot == 1);
01269                 }
01270         }
01271         if (assertPos != 1) { std::swap(cc[1], cc[assertPos]); }
01272         if (ccRepMode == SolverStrategies::cc_rep_dynamic) {
01273                 ccRepMode = double(lbd)/double(decisionLevel()) > .66 ? SolverStrategies::cc_rep_decision : SolverStrategies::cc_rep_uip;
01274         }
01275         if (ccRepMode) {
01276                 maxVar = cc[0].var(), tagged = false, lbd = 1;
01277                 if (ccRepMode == SolverStrategies::cc_rep_decision) {
01278                         // replace cc with decision sequence
01279                         cc.resize(assertLevel+1);
01280                         for (uint32 i = assertLevel; i;){
01281                                 Literal x = ~decision(i--);
01282                                 cc[lbd++] = x;
01283                                 if (x == tagLit)     { tagged = true; }
01284                                 if (x.var() > maxVar){ maxVar = x.var(); }
01285                         }
01286                 }
01287                 else {
01288                         // replace cc with all uip clause
01289                         uint32 marked = cc.size() - 1;
01290                         while (cc.size() > 1) { markSeen(~cc.back()); cc.pop_back(); }
01291                         for (LitVec::const_iterator tr = assign_.trail.end(), next, stop; marked;) {
01292                                 while (!seen(*--tr)) { ; }
01293                                 bool n = --marked != 0 && !reason(*tr).isNull();
01294                                 clearSeen(tr->var());
01295                                 if (n) { for (next = tr, stop = assign_.trail.begin() + levelStart(level(tr->var())); next-- != stop && !seen(*next);) { ; } }
01296                                 if (!n || level(next->var()) != level(tr->var())) {
01297                                         cc.push_back(~*tr);
01298                                         if (tr->var() == tagLit.var()){ tagged = true; }
01299                                         if (tr->var() > maxVar)       { maxVar = tr->var(); }
01300                                 }
01301                                 else {
01302                                         for (reason(*tr, conflict_); !conflict_.empty(); conflict_.pop_back()) {
01303                                                 if (!seen(conflict_.back())) { ++marked; markSeen(conflict_.back()); }
01304                                         }
01305                                 }
01306                         }
01307                         lbd = cc.size();
01308                 }
01309         }
01310         info.setActivity(ccInfo_.activity());
01311         info.setLbd(lbd);
01312         info.setTagged(tagged);
01313         info.setAux(auxVar(maxVar));
01314         return assertLevel;
01315 }
01316 
01317 // (inefficient) default implementation 
01318 bool Constraint::minimize(Solver& s, Literal p, CCMinRecursive* rec) {
01319         LitVec temp;
01320         reason(s, p, temp);
01321         for (LitVec::size_type i = 0; i != temp.size(); ++i) {
01322                 if (!s.ccMinimize(temp[i], rec)) {
01323                         return false;
01324                 }
01325         }
01326         return true;
01327 }
01328 
01329 // Selects next branching literal
01330 bool Solver::decideNextBranch(double f) { 
01331         if (f <= 0.0 || rng.drand() >= f || numFreeVars() == 0) {
01332                 return heuristic_->select(*this);
01333         }
01334         // select randomly
01335         Literal choice;
01336         uint32 maxVar = numVars() + 1; 
01337         for (uint32 v = rng.irand(maxVar);;) {
01338                 if (value(v) == value_free) {
01339                         choice    = heuristic_->selectLiteral(*this, v, 0);
01340                         break;
01341                 }
01342                 if (++v == maxVar) { v = 1; }
01343         }
01344         return assume(choice);
01345 }
01346 // Removes up to remFrac% of the learnt nogoods but
01347 // keeps those that are locked or are highly active.
01348 Solver::DBInfo Solver::reduceLearnts(float remFrac, const ReduceStrategy& rs) {
01349         uint32 oldS = numLearntConstraints();
01350         uint32 remM = static_cast<uint32>(oldS * std::max(0.0f, remFrac));
01351         DBInfo r    = {0,0,0};
01352         CmpScore cmp(learnts_, (ReduceStrategy::Score)rs.score, rs.glue);
01353         if (remM >= oldS || !remM || rs.algo == ReduceStrategy::reduce_sort) {
01354                 r = reduceSortInPlace(remM, cmp, false);
01355         }
01356         else if (rs.algo == ReduceStrategy::reduce_stable) { r = reduceSort(remM, cmp);  }
01357         else if (rs.algo == ReduceStrategy::reduce_heap)   { r = reduceSortInPlace(remM, cmp, true);}
01358         else                                               { r = reduceLinear(remM, cmp); }
01359         stats.addDeleted(oldS - r.size);
01360         shrinkVecTo(learnts_, r.size);
01361         return r;
01362 }
01363 
01364 // Removes up to maxR of the learnt nogoods.
01365 // Keeps those that are locked or have a high activity and
01366 // does not reorder learnts_.
01367 Solver::DBInfo Solver::reduceLinear(uint32 maxR, const CmpScore& sc) {
01368         // compute average activity
01369         uint64 scoreSum  = 0;
01370         for (LitVec::size_type i = 0; i != learnts_.size(); ++i) {
01371                 scoreSum += sc.score(static_cast<LearntConstraint*>(learnts_[i])->activity());
01372         }
01373         double avgAct    = (scoreSum / (double) numLearntConstraints());
01374         // constraints with socre > 1.5 times the average are "active"
01375         double scoreThresh = avgAct * 1.5;
01376         double scoreMax    = (double)sc.score(Activity(Activity::MAX_ACT, 1));
01377         if (scoreThresh > scoreMax) {
01378                 scoreThresh = (scoreMax + (scoreSum / (double) numLearntConstraints())) / 2.0;
01379         }
01380         // remove up to maxR constraints but keep "active" and locked once
01381         const uint32 glue = sc.glue;
01382         DBInfo       res  = {0,0,0};
01383         for (LitVec::size_type i = 0; i != learnts_.size(); ++i) {
01384                 LearntConstraint* c = static_cast<LearntConstraint*>(learnts_[i]);
01385                 Activity a          = c->activity();
01386                 bool isLocked       = c->locked(*this);
01387                 bool isGlue         = (sc.score(a) > scoreThresh || a.lbd() <= glue);
01388                 if (maxR == 0 || isLocked || isGlue) {
01389                         res.pinned             += isGlue;
01390                         res.locked             += isLocked;
01391                         learnts_[res.size++]    = c;
01392                         c->decreaseActivity();
01393                 }
01394                 else {
01395                         --maxR;
01396                         c->destroy(this, true);
01397                 }
01398         }
01399         return res;
01400 }
01401 
01402 // Sorts learnt constraints by score and removes the
01403 // maxR constraints with the lowest score without
01404 // reordering learnts_.
01405 Solver::DBInfo Solver::reduceSort(uint32 maxR, const CmpScore& sc) {
01406         typedef PodVector<CmpScore::ViewPair>::type HeapType;
01407         maxR              = std::min(maxR, (uint32)learnts_.size());
01408         const uint32 glue = sc.glue;
01409         DBInfo       res  = {0,0,0};
01410         HeapType     heap;
01411         heap.reserve(maxR);
01412         bool isGlue, isLocked;
01413         for (LitVec::size_type i = 0; i != learnts_.size(); ++i) {
01414                 LearntConstraint* c = static_cast<LearntConstraint*>(learnts_[i]);
01415                 CmpScore::ViewPair vp(i, c->activity());
01416                 res.pinned += (isGlue   = (vp.second.lbd() <= glue));
01417                 res.locked += (isLocked = c->locked(*this));
01418                 if (!isLocked && !isGlue) { 
01419                         if (maxR) { // populate heap with first maxR constraints
01420                                 heap.push_back(vp); 
01421                                 if (--maxR == 0) { std::make_heap(heap.begin(), heap.end(), sc); } 
01422                         }
01423                         else if (sc(vp, heap[0])) { // replace max element in heap
01424                                 std::pop_heap(heap.begin(), heap.end(), sc);
01425                                 heap.back() = vp;
01426                                 std::push_heap(heap.begin(), heap.end(), sc);
01427                         }
01428                 }
01429         }
01430         // Remove all constraints in heap - those are "inactive".
01431         for (HeapType::const_iterator it = heap.begin(), end = heap.end(); it != end; ++it) {
01432                 learnts_[it->first]->destroy(this, true);
01433                 learnts_[it->first] = 0;
01434         }
01435         // Cleanup db and decrease activity of remaining constraints.
01436         uint32 j = 0;
01437         for (LitVec::size_type i = 0; i != learnts_.size(); ++i) {
01438                 if (LearntConstraint* c = static_cast<LearntConstraint*>(learnts_[i])) {
01439                         c->decreaseActivity();
01440                         learnts_[j++] = c;
01441                 }
01442         }
01443         res.size = j;
01444         return res;
01445 }
01446 
01447 // Sorts the learnt db by score and removes the first 
01448 // maxR constraints (those with the lowest score). 
01449 Solver::DBInfo Solver::reduceSortInPlace(uint32 maxR, const CmpScore& sc, bool partial) {
01450         maxR                        = std::min(maxR, (uint32)learnts_.size());
01451         ConstraintDB::iterator nEnd = learnts_.begin();
01452         const uint32 glue           = sc.glue;
01453         DBInfo res                  = {0,0,0};
01454         bool isGlue, isLocked;
01455         if (!partial) {
01456                 // sort whole db and remove first maxR constraints
01457                 if (maxR && maxR != learnts_.size()) std::stable_sort(learnts_.begin(), learnts_.end(), sc);
01458                 for (ConstraintDB::iterator it = learnts_.begin(), end = learnts_.end(); it != end; ++it) {
01459                         LearntConstraint* c = static_cast<LearntConstraint*>(*it);
01460                         res.pinned         += (isGlue = (c->activity().lbd() <= glue)); 
01461                         res.locked         += (isLocked = c->locked(*this));
01462                         if (!maxR || isLocked || isGlue) { c->decreaseActivity(); *nEnd++ = c; }
01463                         else                             { c->destroy(this, true); --maxR; }
01464                 }
01465         }
01466         else {
01467                 ConstraintDB::iterator hBeg = learnts_.begin();
01468                 ConstraintDB::iterator hEnd = learnts_.begin();
01469                 for (ConstraintDB::iterator it = learnts_.begin(), end = learnts_.end(); it != end; ++it) {
01470                         LearntConstraint* c = static_cast<LearntConstraint*>(*it);
01471                         res.pinned         += (isGlue = (c->activity().lbd() <= glue)); 
01472                         res.locked         += (isLocked = c->locked(*this));
01473                         if      (isLocked || isGlue) { continue; }
01474                         else if (maxR)               {
01475                                 *it     = *hEnd;
01476                                 *hEnd++ = c;
01477                                 if (--maxR == 0) { std::make_heap(hBeg, hEnd, sc); }
01478                         }
01479                         else if (sc(c, learnts_[0])) {
01480                                 std::pop_heap(hBeg, hEnd, sc);
01481                                 *it      = *(hEnd-1);
01482                                 *(hEnd-1)= c;
01483                                 std::push_heap(hBeg, hEnd, sc);
01484                         }
01485                 }
01486                 // remove all constraints in heap
01487                 for (ConstraintDB::iterator it = hBeg; it != hEnd; ++it) {
01488                         static_cast<LearntConstraint*>(*it)->destroy(this, true);
01489                 }
01490                 // copy remaining constraints down
01491                 for (ConstraintDB::iterator it = hEnd, end = learnts_.end(); it != end; ++it) {
01492                         LearntConstraint* c = static_cast<LearntConstraint*>(*it);
01493                         c->decreaseActivity();
01494                         *nEnd++ = c;
01495                 }
01496         }
01497         res.size = static_cast<uint32>(std::distance(learnts_.begin(), nEnd));
01498         return res;     
01499 }
01500 
01501 uint32 Solver::countLevels(const Literal* first, const Literal* last, uint32 maxLevel) {
01502         if (maxLevel < 2)    { return uint32(maxLevel && first != last); }
01503         if (++lbdTime_ != 0) { lbdStamp_.resize(levels_.size()+1, lbdTime_-1); }
01504         else                 { lbdStamp_.assign(levels_.size()+1, lbdTime_); lbdTime_ = 1; }
01505         lbdStamp_[0] = lbdTime_;
01506         uint32 levels= 0;
01507         for (uint32 lev; first != last; ++first) {
01508                 lev = level(first->var());
01509                 if (lbdStamp_[lev] != lbdTime_) {
01510                         lbdStamp_[lev] = lbdTime_;
01511                         if (++levels == maxLevel) { break; }
01512                 }
01513         }
01514         return levels;
01515 }
01516 
01517 uint64 Solver::updateBranch(uint32 cfl) {
01518         int32 dl = (int32)decisionLevel(), xl = static_cast<int32>(cflStamp_.size())-1;
01519         if      (xl > dl) { do { cfl += cflStamp_.back(); cflStamp_.pop_back(); } while (--xl != dl); }
01520         else if (dl > xl) { cflStamp_.insert(cflStamp_.end(), dl - xl, 0); }
01521         return cflStamp_.back() += cfl;
01522 }
01524 // The basic DPLL-like search-function
01526 ValueRep Solver::search(SearchLimits& limit, double rf) {
01527         assert(!isFalse(tagLiteral()));
01528         uint64 local = limit.local != UINT64_MAX ? limit.local : 0;
01529         rf           = std::max(0.0, std::min(1.0, rf));
01530         if (local && decisionLevel() == rootLevel()) { cflStamp_.assign(decisionLevel()+1, 0); }
01531         temp_.clear();
01532         do {
01533                 for (uint32 conflicts = hasConflict() || !propagate() || !simplify();;) {
01534                         if (conflicts) {
01535                                 for (conflicts = 1; resolveConflict() && !propagate(); ) { ++conflicts; }
01536                                 limit.conflicts -= conflicts < limit.conflicts ? conflicts : limit.conflicts;
01537                                 if (local && updateBranch(conflicts) >= local)              { limit.local = 0; }
01538                                 if (hasConflict() || (decisionLevel() == 0 && !simplify())) { return value_false; }
01539                                 if ((limit.reached() || learntLimit(limit))&&numFreeVars()) { return value_free;  }
01540                         }
01541                         if (decideNextBranch(rf)) { conflicts = !propagate(); }
01542                         else                      { break; }
01543                 }
01544         } while (!post_.isModel(*this));
01545         temp_.clear();
01546         model.clear(); model.reserve(numVars()+1);
01547         for (Var v = 0; v <= numVars(); ++v) { model.push_back(value(v)); }
01548         if (satPrepro()) { satPrepro()->extendModel(model, temp_); }
01549         return value_true;
01550 }
01551 
01552 }


clasp
Author(s): Benjamin Kaufmann
autogenerated on Thu Aug 27 2015 12:41:39