00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
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
00032
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
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
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
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
00144
00145 for (DecisionLevels::size_type i = 0; i != levels_.size(); ++i) {
00146 delete levels_[i].undo;
00147 }
00148
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
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;
00194 strategy.loadCfg= 0;
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) {
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();
00223 initPost_ = 0;
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();
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
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
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) {
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
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
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
00384 if (!popRootLevel(0) || !simplify() || !propagate()) { return false; }
00385
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
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
00441
00442
00443 conflict_.push_back(negLit(0));
00444
00445 conflict_.push_back(Literal::fromRep(rootLevel()));
00446
00447 conflict_.push_back(Literal::fromRep(assign_.front));
00448 }
00449
00450
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()) {
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
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
00549
00550
00551
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
00643 uint32 saved = assign_.data(p.var());
00644 assign_.setData(p.var(), data);
00645
00646 a.reason(*this, p, conflict_);
00647
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);
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
00704 if (idx < maxIdx && !btig.propagate(*this, p)) {
00705 return false;
00706 }
00707
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
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);
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
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
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
00899 x->clear();
00900 x->push_back((Constraint*)undoHead_);
00901 undoHead_ = x;
00902 }
00903
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
00922
00923
00924 uint32 Solver::analyzeConflict() {
00925
00926 heuristic_->undoUntil( *this, levels_.back().trailPos );
00927 uint32 onLevel = 0;
00928 uint32 resSize = 0;
00929 Literal p;
00930 cc_.assign(1, p);
00931 Antecedent lhs, rhs, last;
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
00959 otfs(lhs, rhs, p, onLevel == 1);
00960 }
00961 assert(onLevel > 0 && "CONFLICT MUST BE ANALYZED ON CONFLICT LEVEL!");
00962
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;
00973 last = rhs;
00974 reason(p, conflict_);
00975 }
00976 cc_[0] = ~p;
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
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
01040
01041
01042
01043
01044
01045
01046 uint32 Solver::simplifyConflictClause(LitVec& cc, ClauseInfo& info, ClauseHead* rhs) {
01047
01048 temp_.clear();
01049 uint32 onAssert = ccMinimize(cc, temp_, strategy.ccMinAntes, ccMin_);
01050 uint32 jl = cc.size() > 1 ? level(cc[1].var()) : 0;
01051
01052 for (LitVec::size_type x = 0, stop = temp_.size(); x != stop; ++x) {
01053 clearSeen(temp_[x].var());
01054 }
01055
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
01064 conflict_.clear();
01065 ante.reason(*this, ~cc[1], conflict_);
01066 ccResolve(cc, 1, conflict_);
01067 }
01068 clearSeen(cc[0].var());
01069 }
01070
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
01078
01079
01080 open -= level(it->var()) > 0 && seen(it->var());
01081 }
01082 rhs = open ? 0 : otfsRemove(rhs, &cc);
01083 if (rhs) {
01084
01085
01086 ClauseHead::BoolPair r(true, false);
01087 if (cc_.size() < conflict_.size()) {
01088
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
01100 uint32 repMode = cc.size() < std::max(strategy.compress, decisionLevel()+1) ? 0 : strategy.ccRepMode;
01101 jl = finalizeConflictClause(cc, info, repMode);
01102
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
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
01124
01125
01126
01127
01128
01129
01130
01131
01132
01133 uint32 Solver::ccMinimize(LitVec& cc, LitVec& removed, uint32 antes, CCMinRecursive* ccMin) {
01134 if (ccMin) { ccMin->init(numVars()+1); }
01135
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
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
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
01203
01204
01205
01206
01207
01208
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
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
01243
01244
01245
01246
01247 uint32 Solver::finalizeConflictClause(LitVec& cc, ClauseInfo& info, uint32 ccRepMode) {
01248
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
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
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
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
01330 bool Solver::decideNextBranch(double f) {
01331 if (f <= 0.0 || rng.drand() >= f || numFreeVars() == 0) {
01332 return heuristic_->select(*this);
01333 }
01334
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
01347
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
01365
01366
01367 Solver::DBInfo Solver::reduceLinear(uint32 maxR, const CmpScore& sc) {
01368
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
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
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
01403
01404
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) {
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])) {
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
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
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
01448
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
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
01487 for (ConstraintDB::iterator it = hBeg; it != hEnd; ++it) {
01488 static_cast<LearntConstraint*>(*it)->destroy(this, true);
01489 }
01490
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
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 }