00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020 #include <clasp/satelite.h>
00021 #include <clasp/clause.h>
00022
00023 #ifdef _MSC_VER
00024 #pragma warning (disable : 4200) // nonstandard extension used : zero-sized array
00025 #endif
00026 namespace Clasp { namespace SatElite {
00028
00029
00031 SatElite::SatElite()
00032 : occurs_(0)
00033 , elimHeap_(LessOccCost(occurs_))
00034 , qFront_(0)
00035 , facts_(0) {
00036 }
00037
00038 SatElite::~SatElite() {
00039 SatElite::doCleanUp();
00040 }
00041
00042 void SatElite::reportProgress(Progress::EventOp id, uint32 curr, uint32 max) {
00043 ctx_->report(Progress(this, id, curr, max));
00044 }
00045
00046 Clasp::SatPreprocessor* SatElite::clone() {
00047 SatElite* cp = new SatElite();
00048 return cp;
00049 }
00050
00051 void SatElite::doCleanUp() {
00052 delete [] occurs_; occurs_ = 0;
00053 ClauseList().swap(resCands_);
00054 VarVec().swap(posT_);
00055 VarVec().swap(negT_);
00056 LitVec().swap(resolvent_);
00057 VarVec().swap(queue_);
00058 elimHeap_.clear();
00059 qFront_ = facts_ = 0;
00060 }
00061
00062 SatPreprocessor::Clause* SatElite::popSubQueue() {
00063 if (Clause* c = clause( queue_[qFront_++] )) {
00064 c->setInQ(false);
00065 return c;
00066 }
00067 return 0;
00068 }
00069
00070 void SatElite::addToSubQueue(uint32 clauseId) {
00071 assert(clause(clauseId) != 0);
00072 if (!clause(clauseId)->inQ()) {
00073 queue_.push_back(clauseId);
00074 clause(clauseId)->setInQ(true);
00075 }
00076 }
00077
00078 void SatElite::attach(uint32 clauseId, bool initialClause) {
00079 Clause& c = *clause(clauseId);
00080 c.abstraction() = 0;
00081 for (uint32 i = 0; i != c.size(); ++i) {
00082 Var v = c[i].var();
00083 occurs_[v].add(clauseId, c[i].sign());
00084 occurs_[v].unmark();
00085 c.abstraction() |= Clause::abstractLit(c[i]);
00086 if (elimHeap_.is_in_queue(v)) {
00087 elimHeap_.decrease(v);
00088 }
00089 else if (initialClause) {
00090 updateHeap(v);
00091 }
00092 }
00093 occurs_[c[0].var()].addWatch(clauseId);
00094 addToSubQueue(clauseId);
00095 stats.clAdded += !initialClause;
00096 }
00097
00098 void SatElite::detach(uint32 id) {
00099 Clause& c = *clause(id);
00100 occurs_[c[0].var()].removeWatch(id);
00101 for (uint32 i = 0; i != c.size(); ++i) {
00102 Var v = c[i].var();
00103 occurs_[v].remove(id, c[i].sign(), false);
00104 updateHeap(v);
00105 }
00106 destroyClause(id);
00107 }
00108
00109 void SatElite::bceVeRemove(uint32 id, bool freeId, Var ev, bool blocked) {
00110 Clause& c = *clause(id);
00111 occurs_[c[0].var()].removeWatch(id);
00112 uint32 pos = 0;
00113 for (uint32 i = 0; i != c.size(); ++i) {
00114 Var v = c[i].var();
00115 if (v != ev) {
00116 occurs_[v].remove(id, c[i].sign(), freeId);
00117 updateHeap(v);
00118 }
00119 else {
00120 occurs_[ev].remove(id, c[i].sign(), false);
00121 pos = i;
00122 }
00123 }
00124 std::swap(c[0], c[pos]);
00125 c.setMarked(blocked);
00126 eliminateClause(id);
00127 }
00128
00129 bool SatElite::initPreprocess(Options& opts) {
00130 reportProgress(Progress::event_algorithm, 0,100);
00131 opts_ = &opts;
00132 occurs_ = new OccurList[ctx_->numVars()+1];
00133 qFront_ = 0;
00134 occurs_[0].bce = (opts.type == Options::sat_pre_full);
00135 return true;
00136 }
00137 bool SatElite::doPreprocess() {
00138
00139 for (uint32 i = 0, end = numClauses(); i != end; ++i) {
00140 attach(i, true);
00141 }
00142
00143 timeout_ = opts_->limTime ? time(0) + opts_->limTime : std::numeric_limits<std::time_t>::max();
00144 for (uint32 i = 0, end = opts_->limIters ? opts_->limIters : UINT32_MAX; queue_.size()+elimHeap_.size() > 0; ++i) {
00145 if (!backwardSubsume()) { return false; }
00146 if (timeout() || i == end){ break; }
00147 if (!eliminateVars()) { return false; }
00148 }
00149 reportProgress(Progress::event_algorithm, 100,100);
00150 return true;
00151 }
00152
00153
00154
00155
00156
00157 bool SatElite::propagateFacts() {
00158 Solver* s = ctx_->master();
00159 assert(s->queueSize() == 0);
00160 while (facts_ != s->numAssignedVars()) {
00161 Literal l = s->trail()[facts_++];
00162 OccurList& ov = occurs_[l.var()];
00163 ClRange cls = occurs_[l.var()].clauseRange();
00164 for (ClIter x = cls.first; x != cls.second; ++x) {
00165 if (clause(x->var()) == 0) { continue; }
00166 else if (x->sign() == l.sign()) { detach(x->var()); }
00167 else if (!strengthenClause(x->var(), ~l)){ return false; }
00168 }
00169 ov.clear();
00170 ov.mark(!l.sign());
00171 }
00172 assert(s->queueSize() == 0);
00173 return true;
00174 }
00175
00176
00177 bool SatElite::backwardSubsume() {
00178 if (!propagateFacts()) return false;
00179 while (qFront_ != queue_.size()) {
00180 if ((qFront_ & 8191) == 0) {
00181 if (timeout()) break;
00182 if (queue_.size() > 1000) reportProgress(Progress::event_subsumption, qFront_, queue_.size());
00183 }
00184 if (peekSubQueue() == 0) { ++qFront_; continue; }
00185 Clause& c = *popSubQueue();
00186
00187 Literal best = c[0];
00188 for (uint32 i = 1; i < c.size(); ++i) {
00189 if (occurs_[c[i].var()].numOcc() < occurs_[best.var()].numOcc()) {
00190 best = c[i];
00191 }
00192 }
00193
00194 ClWList& cls = occurs_[best.var()].refs;
00195 Literal res = negLit(0);
00196 uint32 j = 0;
00197
00198 for (uint32 i = 0, end = cls.left_size(); i != end; ++i) {
00199 Literal cl = cls.left(i);
00200 uint32 otherId = cl.var();
00201 Clause* other = clause(otherId);
00202 if (other && other!= &c && (res = subsumes(c, *other, best.sign()==cl.sign()?posLit(0):best)) != negLit(0)) {
00203 if (res == posLit(0)) {
00204
00205 detach(otherId);
00206 other = 0;
00207 }
00208 else {
00209
00210
00211 res = ~res;
00212 occurs_[res.var()].remove(otherId, res.sign(), res.var() != best.var());
00213 updateHeap(res.var());
00214 if (!strengthenClause(otherId, res)) { return false; }
00215 if (res.var() == best.var() || !clause(otherId)) { other = 0; }
00216 }
00217 }
00218 if (other && j++ != i) { cls.left(j-1) = cl; }
00219 }
00220 cls.shrink_left(cls.left_begin()+j);
00221 occurs_[best.var()].dirty = 0;
00222 assert(occurs_[best.var()].numOcc() == (uint32)cls.left_size());
00223 if (!propagateFacts()) return false;
00224 }
00225 queue_.clear();
00226 qFront_ = 0;
00227 return true;
00228 }
00229
00230
00231
00232
00233
00234
00235
00236 Literal SatElite::subsumes(const Clause& c, const Clause& other, Literal res) const {
00237 if (other.size() < c.size() || (c.abstraction() & ~other.abstraction()) != 0) {
00238 return negLit(0);
00239 }
00240 if (c.size() < 10 || other.size() < 10) {
00241 for (uint32 i = 0; i != c.size(); ++i) {
00242 for (uint32 j = 0; j != other.size(); ++j) {
00243 if (c[i].var() == other[j].var()) {
00244 if (c[i].sign() == other[j].sign()) { goto found; }
00245 else if (res != posLit(0) && res!=c[i]) { return negLit(0); }
00246 res = c[i];
00247 goto found;
00248 }
00249 }
00250 return negLit(0);
00251 found:;
00252 }
00253 }
00254 else {
00255 markAll(&other[0], other.size());
00256 for (uint32 i = 0; i != c.size(); ++i) {
00257 if (occurs_[c[i].var()].litMark == 0) { res = negLit(0); break; }
00258 if (occurs_[c[i].var()].marked(!c[i].sign())) {
00259 if (res != posLit(0)&&res!=c[i]) { res = negLit(0); break; }
00260 res = c[i];
00261 }
00262 }
00263 unmarkAll(&other[0], other.size());
00264 }
00265 return res;
00266 }
00267
00268 uint32 SatElite::findUnmarkedLit(const Clause& c, uint32 x) const {
00269 for (; x != c.size() && occurs_[c[x].var()].marked(c[x].sign()); ++x)
00270 ;
00271 return x;
00272 }
00273
00274
00275
00276
00277
00278
00279
00280
00281 bool SatElite::subsumed(LitVec& cl) {
00282 Literal l;
00283 uint32 x = 0;
00284 uint32 str = 0;
00285 LitVec::size_type j = 0;
00286 for (LitVec::size_type i = 0; i != cl.size(); ++i) {
00287 l = cl[i];
00288 if (occurs_[l.var()].litMark == 0) { --str; continue; }
00289 ClWList& cls = occurs_[l.var()].refs;
00290 WIter wj = cls.right_begin();
00291 for (WIter w = wj, end = cls.right_end(); w != end; ++w) {
00292 Clause& c = *clause(*w);
00293 if (c[0] == l) {
00294 if ( (x = findUnmarkedLit(c, 1)) == c.size() ) {
00295 while (w != end) { *wj++ = *w++; }
00296 cls.shrink_right( wj );
00297 return true;
00298 }
00299 c[0] = c[x];
00300 c[x] = l;
00301 occurs_[c[0].var()].addWatch(*w);
00302 if (occurs_[c[0].var()].litMark != 0 && findUnmarkedLit(c, x+1) == c.size()) {
00303 occurs_[c[0].var()].unmark();
00304 ++str;
00305 }
00306 }
00307 else if ( findUnmarkedLit(c, 1) == c.size() ) {
00308 occurs_[l.var()].unmark();
00309 while (w != end) { *wj++ = *w++; }
00310 cls.shrink_right( wj );
00311 goto removeLit;
00312 }
00313 else { *wj++ = *w; }
00314 }
00315 cls.shrink_right(wj);
00316 if (j++ != i) { cl[j-1] = cl[i]; }
00317 removeLit:;
00318 }
00319 cl.erase(cl.begin()+j, cl.end());
00320 if (str > 0) {
00321 for (LitVec::size_type i = 0; i != cl.size();) {
00322 if (occurs_[cl[i].var()].litMark == 0) {
00323 cl[i] = cl.back();
00324 cl.pop_back();
00325 if (--str == 0) break;
00326 }
00327 else { ++i; }
00328 }
00329 }
00330 return false;
00331 }
00332
00333
00334
00335 bool SatElite::strengthenClause(uint32 clauseId, Literal l) {
00336 Clause& c = *clause(clauseId);
00337 if (c[0] == l) {
00338 occurs_[c[0].var()].removeWatch(clauseId);
00339
00340
00341 occurs_[c[1].var()].addWatch(clauseId);
00342 }
00343 ++stats.litsRemoved;
00344 c.strengthen(l);
00345 if (c.size() == 1) {
00346 Literal unit = c[0];
00347 detach(clauseId);
00348 return ctx_->master()->force(unit, 0) && ctx_->master()->propagate();
00349 }
00350 addToSubQueue(clauseId);
00351 return true;
00352 }
00353
00354
00355
00356 SatElite::ClRange SatElite::splitOcc(Var v, bool mark) {
00357 ClRange cls = occurs_[v].clauseRange();
00358 occurs_[v].dirty = 0;
00359 posT_.clear(); negT_.clear();
00360 ClIter j = cls.first;
00361 for (ClIter x = j; x != cls.second; ++x) {
00362 if (Clause* c = clause(x->var())) {
00363 assert(c->marked() == false);
00364 c->setMarked(mark);
00365 (x->sign() ? negT_ : posT_).push_back(x->var());
00366 if (j != x) *j = *x;
00367 ++j;
00368 }
00369 }
00370 occurs_[v].refs.shrink_left(j);
00371 return occurs_[v].clauseRange();
00372 }
00373
00374 void SatElite::markAll(const Literal* lits, uint32 size) const {
00375 for (uint32 i = 0; i != size; ++i) {
00376 occurs_[lits[i].var()].mark(lits[i].sign());
00377 }
00378 }
00379 void SatElite::unmarkAll(const Literal* lits, uint32 size) const {
00380 for (uint32 i = 0; i != size; ++i) {
00381 occurs_[lits[i].var()].unmark();
00382 }
00383 }
00384
00385
00386
00387
00388
00389 bool SatElite::bceVe(Var v, uint32 maxCnt) {
00390 Solver* s = ctx_->master();
00391 if (s->value(v) != value_free) return true;
00392 assert(!ctx_->varInfo(v).frozen() && !ctx_->eliminated(v));
00393 resCands_.clear();
00394
00395
00396 uint32 bce = opts_->bce();
00397 ClRange cls = splitOcc(v, bce > 1);
00398 uint32 cnt = 0;
00399 uint32 markMax = ((uint32)negT_.size() * (bce>1));
00400 uint32 blocked = 0;
00401 bool stop = false;
00402 Clause* lhs, *rhs;
00403 for (VarVec::const_iterator i = posT_.begin(); i != posT_.end() && !stop; ++i) {
00404 lhs = clause(*i);
00405 markAll(&(*lhs)[0], lhs->size());
00406 lhs->setMarked(bce != 0);
00407 for (VarVec::const_iterator j = negT_.begin(); j != negT_.end(); ++j) {
00408 if (!trivialResolvent(*(rhs = clause(*j)), v)) {
00409 markMax -= rhs->marked();
00410 rhs->setMarked(false);
00411 lhs->setMarked(false);
00412 if (++cnt <= maxCnt) {
00413 resCands_.push_back(lhs);
00414 resCands_.push_back(rhs);
00415 }
00416 else if (!markMax) {
00417 stop = (bce == 0);
00418 break;
00419 }
00420 }
00421 }
00422 unmarkAll(&(*lhs)[0], lhs->size());
00423 if (lhs->marked()) {
00424 posT_[blocked++] = *i;
00425 }
00426 }
00427 if (cnt <= maxCnt) {
00428
00429 ctx_->eliminate(v);
00430
00431
00432 for (ClIter it = cls.first; it != cls.second; ++it) {
00433
00434 if (clause(it->var())) {
00435 bool freeId = (cnt && cnt--);
00436 bceVeRemove(it->var(), freeId, v, false);
00437 }
00438 }
00439
00440 assert( resCands_.size() % 2 == 0 );
00441 ClIter it = cls.first;
00442 for (VarVec::size_type i = 0; i != resCands_.size(); i+=2, ++it) {
00443 if (!addResolvent(it->var(), *resCands_[i], *resCands_[i+1])) {
00444 return false;
00445 }
00446 }
00447 assert(occurs_[v].numOcc() == 0);
00448
00449 occurs_[v].clear();
00450 }
00451 else if ( (blocked + markMax) > 0 ) {
00452
00453 for (uint32 i = 0; i != blocked; ++i) {
00454 bceVeRemove(posT_[i], false, v, true);
00455 }
00456 for (VarVec::const_iterator it = negT_.begin(); markMax; ++it) {
00457 if ( (rhs = clause(*it))->marked() ) {
00458 bceVeRemove(*it, false, v, true);
00459 --markMax;
00460 }
00461 }
00462 }
00463 return opts_->limIters != 0 || backwardSubsume();
00464 }
00465
00466 bool SatElite::bce() {
00467 uint32 ops = 0;
00468 for (ClWList& bce= occurs_[0].refs; bce.right_size() != 0; ++ops) {
00469 Var v = *(bce.right_end()-1);
00470 bce.pop_right();
00471 occurs_[v].bce=0;
00472 if ((ops & 1023) == 0) {
00473 if (timeout()) { bce.clear(); return true; }
00474 if ((ops & 8191) == 0) { reportProgress(Progress::event_bce, ops, 1+bce.size()); }
00475 }
00476 if (!cutoff(v) && !bceVe(v, 0)) { return false; }
00477 }
00478 return true;
00479 }
00480
00481 bool SatElite::eliminateVars() {
00482 Var v = 0;
00483 uint32 occ = 0;
00484 if (!bce()) return false;
00485 for (uint32 ops = 0; !elimHeap_.empty(); ++ops) {
00486 v = elimHeap_.top(); elimHeap_.pop();
00487 occ = occurs_[v].numOcc();
00488 if ((ops & 1023) == 0) {
00489 if (timeout()) { elimHeap_.clear(); return true; }
00490 if ((ops & 8191) == 0) { reportProgress(Progress::event_var_elim, ops, 1+elimHeap_.size()); }
00491 }
00492 if (!cutoff(v) && !bceVe(v, occ)) {
00493 return false;
00494 }
00495 }
00496 return opts_->limIters != 0 || bce();
00497 }
00498
00499
00500 bool SatElite::trivialResolvent(const Clause& c2, Var v) const {
00501 for (uint32 i = 0, end = c2.size(); i != end; ++i) {
00502 Literal x = c2[i];
00503 if (occurs_[x.var()].marked(!x.sign()) && x.var() != v) {
00504 return true;
00505 }
00506 }
00507 return false;
00508 }
00509
00510
00511
00512 bool SatElite::addResolvent(uint32 id, const Clause& lhs, const Clause& rhs) {
00513 resolvent_.clear();
00514 Solver* s = ctx_->master();
00515 assert(lhs[0] == ~rhs[0]);
00516 uint32 i, end;
00517 Literal l;
00518 for (i = 1, end = lhs.size(); i != end; ++i) {
00519 l = lhs[i];
00520 if (!s->isFalse(l)) {
00521 if (s->isTrue(l)) goto unmark;
00522 occurs_[l.var()].mark(l.sign());
00523 resolvent_.push_back(l);
00524 }
00525 }
00526 for (i = 1, end = rhs.size(); i != end; ++i) {
00527 l = rhs[i];
00528 if (!s->isFalse(l) && !occurs_[l.var()].marked(l.sign())) {
00529 if (s->isTrue(l)) goto unmark;
00530 occurs_[l.var()].mark(l.sign());
00531 resolvent_.push_back(l);
00532 }
00533 }
00534 if (!subsumed(resolvent_)) {
00535 if (resolvent_.empty()) { return false; }
00536 if (resolvent_.size()==1) {
00537 occurs_[resolvent_[0].var()].unmark();
00538 return s->force(resolvent_[0], 0) && s->propagate() && propagateFacts();
00539 }
00540 setClause(id, resolvent_);
00541 attach(id, false);
00542 return true;
00543 }
00544 unmark:
00545 if (!resolvent_.empty()) {
00546 unmarkAll(&resolvent_[0], resolvent_.size());
00547 }
00548 return true;
00549 }
00550
00551
00552 void SatElite::doExtendModel(ValueVec& m, LitVec& unconstr) {
00553 const ValueRep value_eliminated = 4u;
00554 if (!elimTop_) return;
00555
00556
00557 uint32 uv = 0;
00558 uint32 us = unconstr.size();
00559 Clause* r = elimTop_;
00560 do {
00561 Literal x = (*r)[0];
00562 Var last = x.var();
00563 bool check = true;
00564 if (!r->marked()) {
00565
00566 m[last] = value_eliminated;
00567 }
00568 if (uv != us && unconstr[uv].var() == last) {
00569
00570
00571 check = false;
00572 m[last] = trueValue(unconstr[uv]);
00573 ++uv;
00574 }
00575 do {
00576 Clause& c = *r;
00577 if (m[x.var()] != trueValue(x) && check) {
00578 for (uint32 i = 1, end = c.size(); i != end; ++i) {
00579 ValueRep vi = m[c[i].var()] & 3u;
00580 if (vi != falseValue(c[i])) {
00581 x = c[i];
00582 break;
00583 }
00584 }
00585 if (x == c[0]) {
00586
00587
00588 assert(c.marked() || m[x.var()] != falseValue(x));
00589 m[x.var()] = trueValue(x);
00590 check = false;
00591 }
00592 }
00593 r = r->next();
00594 } while (r && (x = (*r)[0]).var() == last);
00595 if (m[last] == value_eliminated) {
00596
00597 m[last] |= value_true;
00598 unconstr.push_back(posLit(last));
00599 }
00600 } while (r);
00601
00602
00603 LitVec::iterator j = unconstr.begin()+us;
00604 for (LitVec::iterator it = j, end = unconstr.end(); it != end; ++it) {
00605 if ((m[it->var()] & value_eliminated) != 0) {
00606
00607
00608 m[it->var()] = value_true;
00609 *j++ = *it;
00610 }
00611 }
00612 unconstr.erase(j, unconstr.end());
00613 }
00614 }
00615 SatPreprocessor* SatPreParams::create(const SatPreParams& opts) {
00616 if (opts.type != 0) { return new SatElite::SatElite(); }
00617 return 0;
00618 }
00619 }