clause.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/clause.h>
00021 #include <clasp/solver.h>
00022 #include <clasp/util/misc_types.h>
00023 #include <algorithm>
00024 
00025 namespace Clasp { namespace Detail {
00026 struct GreaterLevel {
00027         GreaterLevel(const Solver& s) : solver_(s) {}
00028         bool operator()(const Literal& p1, const Literal& p2) const {
00029                 assert(solver_.value(p1.var()) != value_free && solver_.value(p2.var()) != value_free);
00030                 return solver_.level(p1.var()) > solver_.level(p2.var());
00031         }
00032 private:
00033         GreaterLevel& operator=(const GreaterLevel&);
00034         const Solver& solver_;
00035 };
00036 
00037 struct Sink { 
00038         explicit Sink(SharedLiterals* c) : clause(c) {}
00039         ~Sink() { if (clause) clause->release(); }
00040         SharedLiterals* clause;   
00041 };
00042 
00043 void* alloc(uint32 size) {
00044         CLASP_PRAGMA_TODO("replace with CACHE_LINE_ALIGNED alloc")
00045         return ::operator new(size);
00046 }
00047 void free(void* mem) {
00048         ::operator delete(mem);
00049 }
00050 
00051 } // namespace Detail
00052 
00054 // SharedLiterals
00056 SharedLiterals* SharedLiterals::newShareable(const Literal* lits, uint32 size, ConstraintType t, uint32 numRefs) {
00057         void* m = Detail::alloc(sizeof(SharedLiterals)+(size*sizeof(Literal)));
00058         return new (m) SharedLiterals(lits, size, t, numRefs);
00059 }
00060 
00061 SharedLiterals::SharedLiterals(const Literal* a_lits, uint32 size, ConstraintType t, uint32 refs) 
00062         : size_type_( (size << 2) + t ) {
00063         refCount_ = std::max(uint32(1),refs);
00064         std::memcpy(lits_, a_lits, size*sizeof(Literal));
00065 }
00066 
00067 uint32 SharedLiterals::simplify(Solver& s) {
00068         bool   removeFalse = unique();
00069         uint32   newSize   = 0;
00070         Literal* r         = lits_;
00071         Literal* e         = lits_+size();
00072         ValueRep v;
00073         for (Literal* c = r; r != e; ++r) {
00074                 if ( (v = s.value(r->var())) == value_free ) {
00075                         if (c != r) *c = *r;
00076                         ++c; ++newSize;
00077                 }
00078                 else if (v == trueValue(*r)) {
00079                         newSize = 0; break;
00080                 }
00081                 else if (!removeFalse) ++c;
00082         }
00083         if (removeFalse && newSize != size()) {
00084                 size_type_ = (newSize << 2) | (size_type_ & uint32(3));
00085         }
00086         return newSize;
00087 }
00088 
00089 void SharedLiterals::release() {
00090         if (--refCount_ == 0) {
00091                 this->~SharedLiterals();
00092                 Detail::free(this);
00093         }
00094 }
00095 SharedLiterals* SharedLiterals::share() {
00096         ++refCount_;
00097         return this;
00098 }
00099 
00101 // ClauseCreator
00103 ClauseCreator::ClauseCreator(Solver* s) 
00104         : solver_(s)
00105         , flags_(0){ 
00106 }
00107 
00108 ClauseCreator& ClauseCreator::start(ConstraintType t) {
00109         assert(solver_ && (solver_->decisionLevel() == 0 || t != Constraint_t::static_constraint));
00110         literals_.clear();
00111         extra_ = ClauseInfo(t);
00112         return *this;
00113 }
00114 
00115 uint32 ClauseCreator::watchOrder(const Solver& s, Literal p) {
00116         ValueRep value_p = s.value(p.var());
00117         // DL+1,  if isFree(p)
00118         // DL(p), if isFalse(p)
00119         // ~DL(p),if isTrue(p)
00120         uint32   abstr_p = value_p == value_free ? s.decisionLevel()+1 : s.level(p.var()) ^ -(value_p==trueValue(p));
00121         assert(abstr_p > 0 || (s.isFalse(p) && s.level(p.var()) == 0));
00122         return abstr_p;
00123 }
00124 
00125 ClauseRep ClauseCreator::prepare(Solver& s, const Literal* in, uint32 inSize, const ClauseInfo& e, uint32 flags, Literal* out, uint32 outMax) {
00126         assert(out && outMax > 2);
00127         ClauseRep ret  = ClauseRep::prepared(out, 0, e);
00128         uint32 abst_w1 = 0, abst_w2 = 0;
00129         bool simplify  = ((flags & clause_force_simplify) != 0) && inSize > 2 && outMax >= inSize;
00130         Literal tag    = ~s.tagLiteral();
00131         Var     vMax   = 0;
00132         for (uint32 i = 0, j = 0, MAX_OUT = outMax - 1; i != inSize; ++i) {
00133                 Literal p     = in[i];
00134                 uint32 abst_p = watchOrder(s, p);
00135                 if ((abst_p + 1) > 1 && (!simplify || !s.seen(p.var()))) {
00136                         out[j] = p;
00137                         if (p == tag)         { ret.info.setTagged(true); }
00138                         if (p.var() > vMax)   { vMax = p.var();}
00139                         if (simplify)         { s.markSeen(p); }
00140                         if (abst_p > abst_w1) { std::swap(abst_p, abst_w1); std::swap(out[0], out[j]); }
00141                         if (abst_p > abst_w2) { std::swap(abst_p, abst_w2); std::swap(out[1], out[j]); }
00142                         if (j != MAX_OUT)     { ++j;  }
00143                         ++ret.size;
00144                 }
00145                 else if (abst_p == UINT32_MAX || (simplify && abst_p && s.seen(~p))) {
00146                         abst_w1 = UINT32_MAX;
00147                         break;
00148                 }
00149         }
00150         if (simplify) { 
00151                 for (uint32 x = 0, end = ret.size; x != end; ++x) { s.clearSeen(out[x].var()); } 
00152         }
00153         if (abst_w1 == UINT32_MAX || (abst_w2 && out[0].var() == out[1].var())) {
00154                 out[0]   = abst_w1 == UINT32_MAX || out[0] == ~out[1] ? posLit(0) : out[0]; 
00155                 ret.size = 1;
00156         }
00157         ret.info.setAux(s.auxVar(vMax));
00158         return ret;
00159 }
00160 
00161 
00162 ClauseRep ClauseCreator::prepare(Solver& s, LitVec& lits, uint32 flags, const ClauseInfo& info) {
00163         if (lits.empty()) { lits.push_back(negLit(0)); }
00164         if ((flags & clause_no_prepare) == 0 || (flags & clause_force_simplify) != 0) {
00165                 ClauseRep x = prepare(s, &lits[0], (uint32)lits.size(), info, flags, &lits[0]);
00166                 shrinkVecTo(lits, x.size);
00167                 return x;
00168         }
00169         return ClauseRep::prepared(&lits[0], (uint32)lits.size(), info);
00170 }
00171 
00172 ClauseRep ClauseCreator::prepare(bool forceSimplify) {
00173         return prepare(*solver_, literals_, forceSimplify ? clause_force_simplify : 0, extra_);
00174 }
00175 
00176 ClauseCreator::Status ClauseCreator::status(const Solver& s, const Literal* clause_begin, const Literal* clause_end) {
00177         if (clause_end <= clause_begin) { return status_empty; }
00178         Literal temp[3];
00179         ClauseRep x = prepare(const_cast<Solver&>(s), clause_begin, uint32(clause_end - clause_begin), ClauseInfo(), 0, temp, 3);
00180         return status(s, x);
00181 }
00182 
00183 ClauseCreator::Status ClauseCreator::status(const Solver& s, const ClauseRep& c) {
00184         uint32 dl = s.decisionLevel();
00185         uint32 fw = c.size     ? watchOrder(s, c.lits[0]) : 0;
00186         if (fw == UINT32_MAX) { return status_subsumed; }       
00187         uint32 sw = c.size > 1 ? watchOrder(s, c.lits[1]) : 0;
00188         uint32 st = status_open;
00189         if      (fw > varMax)   { st|= status_sat; fw = ~fw; }
00190         else if (fw <= dl)      { st|= (fw ? status_unsat : status_empty); }
00191         if (sw <= dl && fw > sw){ st|= status_unit;  }
00192         return static_cast<Status>(st);
00193 }
00194 
00195 bool ClauseCreator::ignoreClause(const Solver& s, const ClauseRep& c, Status st, uint32 flags) {
00196         uint32 x = (st & (status_sat|status_unsat));
00197         if (x == status_open)  { return false; }
00198         if (x == status_unsat) { return st != status_empty && (flags & clause_not_conflict) != 0; }
00199         return st == status_subsumed || (st == status_sat && ( (flags & clause_not_sat) != 0 || ((flags & clause_not_root_sat) != 0 && s.level(c.lits[0].var()) <= s.rootLevel())));
00200 }
00201 
00202 ClauseCreator::Result ClauseCreator::end(uint32 flags) {
00203         assert(solver_);
00204         flags |= flags_;
00205         return ClauseCreator::create_prepared(*solver_, prepare(*solver_, literals_, flags, extra_), flags);
00206 }
00207 
00208 ClauseHead* ClauseCreator::newProblemClause(Solver& s, const ClauseRep& clause, uint32 flags) {
00209         ClauseHead* ret;
00210         if (clause.size > 2 && s.strategy.initWatches != SolverStrategies::watch_first) {
00211                 uint32 fw = 0, sw = 1;
00212                 if (s.strategy.initWatches == SolverStrategies::watch_rand) {
00213                         fw = s.rng.irand(clause.size);
00214                         do { sw = s.rng.irand(clause.size); } while (sw == fw); 
00215                 }
00216                 else if (s.strategy.initWatches == SolverStrategies::watch_least) {
00217                         uint32 cw1 = s.numWatches(~clause.lits[0]);
00218                         uint32 cw2 = s.numWatches(~clause.lits[1]);
00219                         if (cw1 > cw2) { std::swap(fw, sw); std::swap(cw1, cw2); }
00220                         for (uint32 i = 2; i != clause.size && cw2; ++i) {
00221                                 uint32 p   = i;
00222                                 uint32 cwp = s.numWatches(~clause.lits[i]);
00223                                 if (cwp < cw1) { std::swap(cwp, cw1); std::swap(fw, p); }
00224                                 if (cwp < cw2) { std::swap(cwp, cw2); std::swap(sw, p); }
00225                         }
00226                 }
00227                 std::swap(clause.lits[0], clause.lits[fw]);
00228                 std::swap(clause.lits[1], clause.lits[sw]);
00229         }
00230         if (clause.size <= Clause::MAX_SHORT_LEN || !s.sharedContext()->physicalShareProblem()) {
00231                 ret = Clause::newClause(s, clause);
00232         }
00233         else {
00234                 ret = Clause::newShared(s, SharedLiterals::newShareable(clause.lits, clause.size, clause.info.type(), 1), clause.info, clause.lits, false);
00235         }
00236         if ( (flags & clause_no_add) == 0 ) {
00237                 assert(!clause.info.aux());
00238                 s.add(ret);
00239         }
00240         return ret;
00241 }
00242 
00243 ClauseHead* ClauseCreator::newLearntClause(Solver& s, const ClauseRep& clause, uint32 flags) {
00244         ClauseHead* ret;
00245         Detail::Sink sharedPtr(0);
00246         sharedPtr.clause = s.distribute(clause.lits, clause.size, clause.info);
00247         if (clause.size <= Clause::MAX_SHORT_LEN || sharedPtr.clause == 0) {
00248                 if (!s.isFalse(clause.lits[1]) || !s.strategy.compress || clause.size < s.strategy.compress) {
00249                         ret = Clause::newClause(s, clause);
00250                 }
00251                 else {
00252                         ret = Clause::newContractedClause(s, clause, 2, true);
00253                 }
00254         }
00255         else {
00256                 ret              = Clause::newShared(s, sharedPtr.clause, clause.info, clause.lits, false);
00257                 sharedPtr.clause = 0;
00258         }
00259         if ( (flags & clause_no_add) == 0 ) {
00260                 s.addLearnt(ret, clause.size, clause.info.type());
00261         }
00262         return ret;
00263 }
00264 
00265 ClauseHead* ClauseCreator::newUnshared(Solver& s, SharedLiterals* clause, const Literal* w, const ClauseInfo& e) {
00266         LitVec temp; temp.reserve(clause->size());
00267         temp.assign(w, w+2);
00268         for (const Literal* x = clause->begin(), *end = clause->end(); x != end; ++x) {
00269                 if (watchOrder(s, *x) > 0 && *x != temp[0] && *x != temp[1]) {
00270                         temp.push_back(*x);
00271                 }
00272         }
00273         return Clause::newClause(s, ClauseRep::prepared(&temp[0], (uint32)temp.size(), e));
00274 }
00275 
00276 ClauseCreator::Result ClauseCreator::create_prepared(Solver& s, const ClauseRep& clause, uint32 flags) {
00277         assert(s.decisionLevel() == 0 || (clause.info.learnt() && clause.prep));
00278         Status x = status(s, clause);
00279         if (ignoreClause(s, clause, x, flags)){ 
00280                 return Result(0, x);
00281         }
00282         if (clause.size > 1) {
00283                 Result ret(0, x);
00284                 if (!clause.info.learnt() && s.satPrepro() && !s.sharedContext()->frozen()) {
00285                         return Result(0, s.satPrepro()->addClause(clause.lits, clause.size) ? x : status_unsat);
00286                 }
00287                 if ((flags & clause_no_heuristic) == 0) { s.heuristic()->newConstraint(s, clause.lits, clause.size, clause.info.type()); }
00288                 if (clause.size > 3 || (flags&clause_explicit) != 0 || !s.allowImplicit(clause)) {
00289                         ret.local = clause.info.learnt() ? newLearntClause(s, clause, flags) : newProblemClause(s, clause, flags);
00290                 }
00291                 else {
00292                         // add implicit short rep
00293                         s.add(clause);
00294                 }
00295                 if ((x & (status_unit|status_unsat)) != 0) {
00296                         Antecedent ante(ret.local);
00297                         if (!ret.local){ ante = clause.size == 3 ? Antecedent(~clause.lits[1], ~clause.lits[2]) : Antecedent(~clause.lits[1]); }
00298                         ret.status = s.force(clause.lits[0], s.level(clause.lits[1].var()), ante) ? status_unit : status_unsat;
00299                 }
00300                 return ret;
00301         }
00302         s.add(clause);
00303         return Result(0, !s.hasConflict() ? status_unit : status_unsat);
00304 }
00305 
00306 ClauseCreator::Result ClauseCreator::create(Solver& s, LitVec& lits, uint32 flags, const ClauseInfo& extra) {
00307         return create_prepared(s, prepare(s, lits, flags, extra), flags);
00308 }
00309 
00310 ClauseCreator::Result ClauseCreator::create(Solver& s, const ClauseRep& rep, uint32 flags) {
00311         return create_prepared(s, (rep.prep == 0 && (flags & clause_no_prepare) == 0 
00312                 ? prepare(s, rep.lits, rep.size, rep.info, flags, rep.lits)
00313                 : ClauseRep::prepared(rep.lits, rep.size, rep.info)), flags);
00314 }
00315 
00316 ClauseCreator::Result ClauseCreator::integrate(Solver& s, SharedLiterals* clause, uint32 modeFlags, ConstraintType t) {
00317         assert(!s.hasConflict() && "ClauseCreator::integrate() - precondition violated!");
00318         Detail::Sink shared( (modeFlags & clause_no_release) == 0 ? clause : 0);
00319         // determine state of clause
00320         Literal temp[Clause::MAX_SHORT_LEN]; temp[0] = temp[1] = negLit(0);
00321         ClauseRep x    = prepare(s, clause->begin(), clause->size(), ClauseInfo(t), 0, temp, Clause::MAX_SHORT_LEN);
00322         uint32 impSize = (modeFlags & clause_explicit) != 0 || !s.allowImplicit(x) ? 1 : 3;
00323         Status xs      = status(s, x);
00324         if (ignoreClause(s, x, xs, modeFlags)) {
00325                 return Result(0, xs);
00326         }
00327         Result result(0, xs);
00328         if ((modeFlags & clause_no_heuristic) == 0) { s.heuristic()->newConstraint(s, clause->begin(), clause->size(), t); }
00329         if (x.size > Clause::MAX_SHORT_LEN && s.sharedContext()->physicalShare(t)) {
00330                 result.local  = Clause::newShared(s, clause, x.info, temp, shared.clause == 0);
00331                 shared.clause = 0;
00332         }
00333         else if (x.size > impSize) {
00334                 result.local  = x.size <= Clause::MAX_SHORT_LEN ? Clause::newClause(s, x) : newUnshared(s, clause, temp, x.info);
00335         }
00336         else {
00337                 // unary clause or implicitly shared via binary/ternary implication graph;
00338                 // only check for implication/conflict but do not create
00339                 // a local representation for the clause
00340                 s.stats.addLearnt(x.size, x.info.type());
00341                 modeFlags    |= clause_no_add;
00342         }
00343         if ((modeFlags & clause_no_add) == 0) { s.addLearnt(result.local, x.size, x.info.type()); }
00344         if ((xs & (status_unit|status_unsat)) != 0) {
00345                 Antecedent ante = result.local ? Antecedent(result.local) : Antecedent(~temp[1], ~temp[2]);
00346                 uint32 impLevel = s.level(temp[1].var());
00347                 result.status   = s.force(temp[0], impLevel, ante) ? status_unit : status_unsat;
00348                 if (result.local && (modeFlags & clause_int_lbd) != 0 && result.status != status_unsat) {
00349                         result.local->lbd(s.updateLearnt(negLit(0), clause->begin(), clause->end(), result.local->lbd(), true));
00350                 }
00351         }
00352         return result;
00353 }
00354 ClauseCreator::Result ClauseCreator::integrate(Solver& s, SharedLiterals* clause, uint32 modeFlags) { 
00355         return integrate(s, clause, modeFlags, clause->type());
00356 }
00358 // Clause
00360 void* Clause::alloc(Solver& s, uint32 lits, bool learnt) {
00361         if (lits <= Clause::MAX_SHORT_LEN) {
00362                 if (learnt) { s.addLearntBytes(32); }
00363                 return s.allocSmall();
00364         }
00365         uint32 extra = std::max((uint32)ClauseHead::HEAD_LITS, lits) - ClauseHead::HEAD_LITS; 
00366         uint32 bytes = sizeof(Clause) + (extra)*sizeof(Literal);
00367         if (learnt) { s.addLearntBytes(bytes); }
00368         return Detail::alloc(bytes);
00369 }
00370 
00371 ClauseHead* Clause::newClause(void* mem, Solver& s, const ClauseRep& rep) {
00372         assert(rep.size >= 2 && mem);
00373         return new (mem) Clause(s, rep);
00374 }
00375 
00376 ClauseHead* Clause::newShared(Solver& s, SharedLiterals* shared_lits, const ClauseInfo& e, const Literal* lits, bool addRef) {
00377         return mt::SharedLitsClause::newClause(s, shared_lits, e, lits, addRef);
00378 }
00379 
00380 ClauseHead* Clause::newContractedClause(Solver& s, const ClauseRep& rep, uint32 tailStart, bool extend) {
00381         assert(rep.size >= 2);
00382         if (extend) { std::stable_sort(rep.lits+tailStart, rep.lits+rep.size, Detail::GreaterLevel(s)); }
00383         return new (alloc(s, rep.size, rep.info.learnt())) Clause(s, rep, tailStart, extend);
00384 }
00385 
00386 Clause::Clause(Solver& s, const ClauseRep& rep, uint32 tail, bool extend) 
00387         : ClauseHead(rep.info) {
00388         assert(tail >= rep.size || s.isFalse(rep.lits[tail]));
00389         data_.local.init(rep.size);
00390         if (!isSmall()) {
00391                 // copy literals
00392                 std::memcpy(head_, rep.lits, rep.size*sizeof(Literal));
00393                 tail = std::max(tail, (uint32)ClauseHead::HEAD_LITS);
00394                 if (tail < rep.size) {       // contracted clause
00395                         head_[rep.size-1].watch(); // mark last literal of clause
00396                         Literal t = head_[tail];
00397                         if (s.level(t.var()) > 0) {
00398                                 data_.local.markContracted();
00399                                 if (extend) {
00400                                         s.addUndoWatch(s.level(t.var()), this);
00401                                 }
00402                         }
00403                         data_.local.setSize(tail);
00404                 }
00405         }
00406         else {
00407                 std::memcpy(head_, rep.lits, std::min(rep.size, (uint32)ClauseHead::HEAD_LITS)*sizeof(Literal));
00408                 data_.lits[0] = rep.size > ClauseHead::HEAD_LITS   ? rep.lits[ClauseHead::HEAD_LITS].asUint()   : negLit(0).asUint();
00409                 data_.lits[1] = rep.size > ClauseHead::HEAD_LITS+1 ? rep.lits[ClauseHead::HEAD_LITS+1].asUint() : negLit(0).asUint();
00410                 assert(isSmall() && Clause::size() == rep.size);
00411         }
00412         attach(s);
00413 }
00414 
00415 Clause::Clause(Solver& s, const Clause& other) : ClauseHead(ClauseInfo()) {
00416         info_.rep      = other.info_.rep;
00417         uint32 oSize   = other.size();
00418         data_.local.init(oSize);
00419         if      (!isSmall())      { std::memcpy(head_, other.head_, oSize*sizeof(Literal)); }
00420         else if (other.isSmall()) { std::memcpy(data_.lits, other.data_.lits, (ClauseHead::MAX_SHORT_LEN+1)*sizeof(Literal)); }
00421         else { // this is small, other is not
00422                 std::memcpy(head_, other.head_, ClauseHead::HEAD_LITS*sizeof(Literal));
00423                 std::memcpy(data_.lits, other.head_+ClauseHead::HEAD_LITS, 2*sizeof(Literal));
00424         }
00425         attach(s);
00426 }
00427 
00428 Constraint* Clause::cloneAttach(Solver& other) {
00429         assert(!learnt());
00430         return new (alloc(other, Clause::size(), false)) Clause(other, *this);
00431 }
00432 
00433 void Clause::destroy(Solver* s, bool detachFirst) {
00434         if (s) { 
00435                 if (detachFirst) { Clause::detach(*s); }
00436                 if (learnt())    { s->freeLearntBytes(computeAllocSize()); }
00437         }
00438         void* mem   = static_cast<Constraint*>(this);
00439         bool  small = isSmall();
00440         this->~Clause();
00441         if (!small) { Detail::free(mem); }
00442         else if (s) { s->freeSmall(mem); }
00443 }
00444 
00445 void Clause::detach(Solver& s) {
00446         if (contracted()) {
00447                 Literal* eoc = longEnd();
00448                 if (s.isFalse(*eoc) && s.level(eoc->var()) != 0) {
00449                         s.removeUndoWatch(s.level(eoc->var()), this);
00450                 }
00451         }
00452         ClauseHead::detach(s);
00453 }
00454 
00455 uint32 Clause::computeAllocSize() const {
00456         if (isSmall()) { return 32; }
00457         uint32 rt = sizeof(Clause) - (ClauseHead::HEAD_LITS*sizeof(Literal));
00458         uint32 sz = data_.local.size();
00459         uint32 nw = contracted() + strengthened();
00460         if (nw != 0u) {
00461                 const Literal* eoc = head_ + sz;
00462                 do { nw -= eoc++->watched(); } while (nw); 
00463                 sz = static_cast<uint32>(eoc - head_);
00464         }
00465         return rt + (sz*sizeof(Literal));
00466 }
00467 
00468 bool Clause::updateWatch(Solver& s, uint32 pos) {
00469         uint32 idx = data_.local.idx;
00470         if (!isSmall()) {
00471                 for (Literal* tailS = head_ + ClauseHead::HEAD_LITS, *end = longEnd();;) {
00472                         for (Literal* it  = tailS + idx; it < end; ++it) {
00473                                 if (!s.isFalse(*it)) {
00474                                         std::swap(*it, head_[pos]);
00475                                         data_.local.idx = static_cast<uint32>(++it - tailS);
00476                                         return true;
00477                                 }
00478                         }
00479                         if (idx == 0) { break; }
00480                         end = tailS + idx;
00481                         idx = 0;
00482                 }
00483         }
00484         else if (!s.isFalse(Literal::fromRep(data_.lits[idx=0])) || !s.isFalse(Literal::fromRep(data_.lits[idx=1]))) {
00485                 std::swap(head_[pos].asUint(), data_.lits[idx]);
00486                 return true;
00487         }
00488         return false;
00489 }
00490 
00491 void Clause::reason(Solver& s, Literal p, LitVec& out) {
00492         LitVec::size_type i = out.size();
00493         out.push_back(~head_[p == head_[0]]);
00494         if (!isSentinel(head_[2])) {
00495                 out.push_back(~head_[2]);
00496                 LitRange t = tail();
00497                 for (const Literal* r = t.first; r != t.second; ++r) {
00498                         out.push_back(~*r);
00499                 }
00500                 if (contracted()) {
00501                         const Literal* r = t.second;
00502                         do { out.push_back(~*r); } while (!r++->watched());
00503                 }
00504         }
00505         if (learnt()) { 
00506                 ClauseHead::bumpActivity();
00507                 setLbd(s.updateLearnt(p, &out[0]+i, &out[0]+out.size(), lbd(), !hasLbd())); 
00508         }
00509 }
00510 
00511 bool Clause::minimize(Solver& s, Literal p, CCMinRecursive* rec) {
00512         ClauseHead::bumpActivity();
00513         uint32 other = p == head_[0];
00514         if (!s.ccMinimize(~head_[other], rec) || !s.ccMinimize(~head_[2], rec)) { return false; }
00515         LitRange t = tail();
00516         for (const Literal* r = t.first; r != t.second; ++r) {
00517                 if (!s.ccMinimize(~*r, rec)) { return false; }
00518         }
00519         if (contracted()) {
00520                 do {
00521                         if (!s.ccMinimize(~*t.second, rec)) { return false; }
00522                 } while (!t.second++->watched());
00523         }
00524         return true;
00525 }
00526 
00527 bool Clause::isReverseReason(const Solver& s, Literal p, uint32 maxL, uint32 maxN) {
00528         uint32 other   = p == head_[0];
00529         if (!isRevLit(s, head_[other], maxL) || !isRevLit(s, head_[2], maxL)) { return false; }
00530         uint32 notSeen = !s.seen(head_[other].var()) + !s.seen(head_[2].var());
00531         LitRange t     = tail();
00532         for (const Literal* r = t.first; r != t.second && notSeen <= maxN; ++r) {
00533                 if (!isRevLit(s, *r, maxL)) { return false; }
00534                 notSeen += !s.seen(r->var());
00535         }
00536         if (contracted()) {
00537                 const Literal* r = t.second;
00538                 do { notSeen += !s.seen(r->var()); } while (notSeen <= maxN && !r++->watched());
00539         }
00540         return notSeen <= maxN;
00541 }
00542 
00543 bool Clause::simplify(Solver& s, bool reinit) {
00544         assert(s.decisionLevel() == 0 && s.queueSize() == 0);
00545         if (ClauseHead::satisfied(s)) {
00546                 detach(s);
00547                 return true;
00548         }
00549         LitRange t = tail();
00550         Literal* it= t.first - !isSmall(), *j;
00551         // skip free literals
00552         while (it != t.second && s.value(it->var()) == value_free) { ++it; }
00553         // copy remaining free literals
00554         for (j = it; it != t.second; ++it) {
00555                 if      (s.value(it->var()) == value_free) { *j++ = *it; }
00556                 else if (s.isTrue(*it)) { Clause::detach(s); return true;}
00557         }
00558         // replace any false lits with sentinels
00559         for (Literal* r = j; r != t.second; ++r) { *r = negLit(0); }
00560         if (!isSmall()) {
00561                 uint32 size     = std::max((uint32)ClauseHead::HEAD_LITS, static_cast<uint32>(j-head_));
00562                 data_.local.idx = 0;
00563                 data_.local.setSize(size);
00564                 if (j != t.second && learnt() && !strengthened()) {
00565                         // mark last literal so that we can recompute alloc size later
00566                         t.second[-1].watch();
00567                         data_.local.markStrengthened();
00568                 }
00569                 if (reinit && size > 3) {
00570                         detach(s);
00571                         std::random_shuffle(head_, j, s.rng);
00572                         attach(s);      
00573                 }
00574         }
00575         else if (s.isFalse(head_[2])) {
00576                 head_[2]   = t.first[0];
00577                 t.first[0] = t.first[1];
00578                 t.first[1] = negLit(0);
00579                 --j;
00580         }
00581         return j <= t.first && ClauseHead::toImplication(s);
00582 }
00583 
00584 uint32 Clause::isOpen(const Solver& s, const TypeSet& x, LitVec& freeLits) {
00585         if (!x.inSet(ClauseHead::type()) || ClauseHead::satisfied(s)) {
00586                 return 0;
00587         }
00588         assert(s.queueSize() == 0 && "Watches might be false!");
00589         freeLits.push_back(head_[0]);
00590         freeLits.push_back(head_[1]);
00591         if (!s.isFalse(head_[2])) freeLits.push_back(head_[2]);
00592         ValueRep v;
00593         LitRange t = tail();
00594         for (Literal* r = t.first; r != t.second; ++r) {
00595                 if ( (v = s.value(r->var())) == value_free) {
00596                         freeLits.push_back(*r);
00597                 }
00598                 else if (v == trueValue(*r)) {
00599                         std::swap(head_[2], *r);
00600                         return 0;
00601                 }
00602         }
00603         return ClauseHead::type();
00604 }
00605 
00606 void Clause::undoLevel(Solver& s) {
00607         assert(!isSmall());
00608         uint32   t = data_.local.size();
00609         Literal* r = head_+t;
00610         while (!r->watched() && s.value(r->var()) == value_free) {
00611                 ++t;
00612                 ++r;
00613         }
00614         if (r->watched() || s.level(r->var()) == 0) {
00615                 r->clearWatch();
00616                 t += !isSentinel(*r);
00617                 data_.local.clearContracted();
00618         }
00619         else {
00620                 s.addUndoWatch(s.level(r->var()), this);
00621         }
00622         data_.local.setSize(t);
00623 }
00624 
00625 void Clause::toLits(LitVec& out) const {
00626         out.insert(out.end(), head_, (head_+ClauseHead::HEAD_LITS)-isSentinel(head_[2]));
00627         LitRange t = const_cast<Clause&>(*this).tail();
00628         if (contracted()) { while (!t.second++->watched()) {;} }
00629         out.insert(out.end(), t.first, t.second);
00630 }
00631 
00632 ClauseHead::BoolPair Clause::strengthen(Solver& s, Literal p, bool toShort) {
00633         LitRange t  = tail();
00634         Literal* eoh= head_+ClauseHead::HEAD_LITS;
00635         Literal* eot= t.second;
00636         Literal* it = std::find(head_, eoh, p);
00637         BoolPair ret(false, false);
00638         if (it != eoh) {
00639                 if (it != head_+2) { // update watch
00640                         *it = head_[2];
00641                         s.removeWatch(~p, this);
00642                         Literal* best = it, *n;
00643                         for (n = t.first; n != eot && s.isFalse(*best); ++n) {
00644                                 if (!s.isFalse(*n) || s.level(n->var()) > s.level(best->var())) { 
00645                                         best = n; 
00646                                 }
00647                         }
00648                         std::swap(*it, *best);
00649                         s.addWatch(~*it, ClauseWatch(this));
00650                         it = head_+2;
00651                 }       
00652                 // replace cache literal with literal from tail
00653                 if ((*it  = *t.first) != negLit(0)) {
00654                         eot     = removeFromTail(s, t.first, eot);
00655                 }
00656                 ret.first = true;
00657         }
00658         else if ((it = std::find(t.first, eot, p)) != eot) {
00659                 eot       = removeFromTail(s, it, eot);
00660                 ret.first = true;
00661         }
00662         else if (contracted()) {
00663                 for (; *it != p && !it->watched(); ++it) { ; }
00664                 ret.first = *it == p;
00665                 eot       = *it == p ? removeFromTail(s, it, eot) : it + 1;
00666         }
00667         if (ret.first && ~p == s.tagLiteral()) {
00668                 clearTagged();
00669         }
00670         ret.second = toShort && eot == t.first && toImplication(s);
00671         return ret;
00672 }
00673 
00674 Literal* Clause::removeFromTail(Solver& s, Literal* it, Literal* end) {
00675         assert(it != end || contracted());
00676         if (!contracted()) {
00677                 *it  = *--end;
00678                 *end = negLit(0);
00679                 if (!isSmall()) { 
00680                         data_.local.setSize(data_.local.size()-1);
00681                         data_.local.idx = 0;
00682                 }
00683         }
00684         else {
00685                 uint32 uLev  = s.level(end->var());
00686                 Literal* j   = it;
00687                 while ( !j->watched() ) { *j++ = *++it; }
00688                 *j           = negLit(0);
00689                 uint32 nLev  = s.level(end->var());
00690                 if (uLev != nLev && s.removeUndoWatch(uLev, this) && nLev != 0) {
00691                         s.addUndoWatch(nLev, this);
00692                 }
00693                 if (j != end) { (j-1)->watch(); }
00694                 else          { data_.local.clearContracted(); }
00695                 end = j;
00696         }
00697         if (learnt() && !isSmall() && !strengthened()) {
00698                 end->watch();
00699                 data_.local.markStrengthened();
00700         }
00701         return end;
00702 }
00703 uint32 Clause::size() const {
00704         LitRange t = const_cast<Clause&>(*this).tail();
00705         return !isSentinel(head_[2])
00706                 ? 3u + static_cast<uint32>(t.second - t.first)
00707                 : 2u;
00708 }
00710 // mt::SharedLitsClause
00712 namespace mt {
00713 ClauseHead* SharedLitsClause::newClause(Solver& s, SharedLiterals* shared_lits, const ClauseInfo& e, const Literal* lits, bool addRef) {
00714         return new (s.allocSmall()) SharedLitsClause(s, shared_lits, lits, e, addRef);
00715 }
00716 
00717 SharedLitsClause::SharedLitsClause(Solver& s, SharedLiterals* shared_lits, const Literal* w, const ClauseInfo& e, bool addRef) 
00718         : ClauseHead(e) {
00719         static_assert(sizeof(SharedLitsClause) <= 32, "Unsupported Padding");
00720         data_.shared = addRef ? shared_lits->share() : shared_lits;
00721         std::memcpy(head_, w, std::min((uint32)ClauseHead::HEAD_LITS, shared_lits->size())*sizeof(Literal));
00722         attach(s);
00723         if (learnt()) { s.addLearntBytes(32); }
00724 }
00725 
00726 Constraint* SharedLitsClause::cloneAttach(Solver& other) {
00727         return SharedLitsClause::newClause(other, data_.shared, ClauseInfo(this->type()), head_);
00728 }
00729 
00730 bool SharedLitsClause::updateWatch(Solver& s, uint32 pos) {
00731         Literal  other = head_[1^pos];
00732         for (const Literal* r = data_.shared->begin(), *end = data_.shared->end(); r != end; ++r) {
00733                 // at this point we know that head_[2] is false so we only need to check 
00734                 // that we do not watch the other watched literal twice!
00735                 if (!s.isFalse(*r) && *r != other) {
00736                         head_[pos] = *r; // replace watch
00737                         // try to replace cache literal
00738                         switch( std::min(static_cast<uint32>(8), static_cast<uint32>(end-r)) ) {
00739                                 case 8: if (!s.isFalse(*++r) && *r != other) { head_[2] = *r; return true; }
00740                                 case 7: if (!s.isFalse(*++r) && *r != other) { head_[2] = *r; return true; }
00741                                 case 6: if (!s.isFalse(*++r) && *r != other) { head_[2] = *r; return true; }
00742                                 case 5: if (!s.isFalse(*++r) && *r != other) { head_[2] = *r; return true; }
00743                                 case 4: if (!s.isFalse(*++r) && *r != other) { head_[2] = *r; return true; }
00744                                 case 3: if (!s.isFalse(*++r) && *r != other) { head_[2] = *r; return true; }
00745                                 case 2: if (!s.isFalse(*++r) && *r != other) { head_[2] = *r; return true; }
00746                                 default: return true;
00747                         }
00748                 }
00749         }
00750         return false;
00751 }
00752 
00753 void SharedLitsClause::reason(Solver& s, Literal p, LitVec& out) {
00754         LitVec::size_type i = out.size();
00755         for (const Literal* r = data_.shared->begin(), *end = data_.shared->end(); r != end; ++r) {
00756                 assert(s.isFalse(*r) || *r == p);
00757                 if (*r != p) { out.push_back(~*r); }
00758         }
00759         if (learnt()) { 
00760                 ClauseHead::bumpActivity();
00761                 setLbd(s.updateLearnt(p, &out[0]+i, &out[0]+out.size(), lbd(), !hasLbd())); 
00762         }
00763 }
00764 
00765 bool SharedLitsClause::minimize(Solver& s, Literal p, CCMinRecursive* rec) {
00766         ClauseHead::bumpActivity();
00767         for (const Literal* r = data_.shared->begin(), *end = data_.shared->end(); r != end; ++r) {
00768                 if (*r != p && !s.ccMinimize(~*r, rec)) { return false; }
00769         }
00770         return true;
00771 }
00772 
00773 bool SharedLitsClause::isReverseReason(const Solver& s, Literal p, uint32 maxL, uint32 maxN) {
00774         uint32 notSeen = 0;
00775         for (const Literal* r = data_.shared->begin(), *end = data_.shared->end(); r != end; ++r) {
00776                 if (*r == p) continue;
00777                 if (!isRevLit(s, *r, maxL)) return false;
00778                 if (!s.seen(r->var()) && ++notSeen > maxN) return false;
00779         }
00780         return true;
00781 }
00782 
00783 bool SharedLitsClause::simplify(Solver& s, bool reinit) {
00784         if (ClauseHead::satisfied(s)) {
00785                 detach(s);
00786                 return true;
00787         }
00788         uint32 optSize = data_.shared->simplify(s);
00789         if (optSize == 0) {
00790                 detach(s);
00791                 return true;
00792         }
00793         else if (optSize <= Clause::MAX_SHORT_LEN) {
00794                 Literal lits[Clause::MAX_SHORT_LEN];
00795                 Literal* j = lits;
00796                 for (const Literal* r = data_.shared->begin(), *e = data_.shared->end(); r != e; ++r) {
00797                         if (!s.isFalse(*r)) *j++ = *r;
00798                 }
00799                 uint32 rep= info_.rep;
00800                 // detach & destroy but do not release memory
00801                 detach(s);
00802                 SharedLitsClause::destroy(0, false);
00803                 // construct short clause in "this"
00804                 ClauseHead* h = Clause::newClause(this, s, ClauseRep::prepared(lits, static_cast<uint32>(j-lits)));
00805                 // restore extra data - safe because memory layout has not changed!
00806                 info_.rep = rep;
00807                 return h->simplify(s, reinit);
00808         }
00809         else if (s.isFalse(head_[2])) {
00810                 // try to replace cache lit with non-false literal
00811                 for (const Literal* r = data_.shared->begin(), *e = data_.shared->end(); r != e; ++r) {
00812                         if (!s.isFalse(*r) && std::find(head_, head_+2, *r) == head_+2) {
00813                                 head_[2] = *r;
00814                                 break;
00815                         }
00816                 }
00817         }
00818         return false;
00819 }
00820 
00821 void SharedLitsClause::destroy(Solver* s, bool detachFirst) {
00822         if (s) {
00823                 if (detachFirst) { ClauseHead::detach(*s); }
00824                 if (learnt())    { s->freeLearntBytes(32); }
00825         }
00826         data_.shared->release();
00827         void* mem = this;
00828         this->~SharedLitsClause();
00829         if (s) { s->freeSmall(mem); }
00830 }
00831 
00832 uint32 SharedLitsClause::isOpen(const Solver& s, const TypeSet& x, LitVec& freeLits) {
00833         if (!x.inSet(ClauseHead::type()) || ClauseHead::satisfied(s)) {
00834                 return 0;
00835         }
00836         Literal* head = head_;
00837         ValueRep v;
00838         for (const Literal* r = data_.shared->begin(), *end = data_.shared->end(); r != end; ++r) {
00839                 if ( (v = s.value(r->var())) == value_free ) {
00840                         freeLits.push_back(*r);
00841                 }
00842                 else if (v == trueValue(*r)) {
00843                         head[2] = *r; // remember as cache literal
00844                         return 0;
00845                 }
00846         }
00847         return ClauseHead::type();
00848 }
00849 
00850 void SharedLitsClause::toLits(LitVec& out) const {
00851         out.insert(out.end(), data_.shared->begin(), data_.shared->end());
00852 }
00853 
00854 ClauseHead::BoolPair SharedLitsClause::strengthen(Solver&, Literal, bool) {
00855         return BoolPair(false, false);
00856 }
00857 
00858 uint32 SharedLitsClause::size() const { return data_.shared->size(); }
00859 
00860 } // end namespace mt
00861 
00863 // LoopFormula
00865 LoopFormula* LoopFormula::newLoopFormula(Solver& s, Literal* bodyLits, uint32 numBodies, uint32 bodyToWatch, uint32 numAtoms, const Activity& act) {
00866         uint32 bytes = sizeof(LoopFormula) + (numBodies+numAtoms+3) * sizeof(Literal);
00867         void* mem    = Detail::alloc( bytes );
00868         s.addLearntBytes(bytes);
00869         return new (mem) LoopFormula(s, numBodies+numAtoms, bodyLits, numBodies, bodyToWatch, act);
00870 }
00871 LoopFormula::LoopFormula(Solver& s, uint32 size, Literal* bodyLits, uint32 numBodies, uint32 bodyToWatch, const Activity& act)
00872         : act_(act) {
00873         end_          = numBodies + 2;
00874         size_         = end_+1;
00875         other_        = end_-1;
00876         lits_[0]      = Literal();  // Starting sentinel
00877         lits_[end_-1] = Literal();  // Position of active atom
00878         lits_[end_]   = Literal();  // Ending sentinel - active part
00879         for (uint32 i = size_; i != size+3; ++i) {
00880                 lits_[i] = Literal();
00881         }
00882         // copy bodies: S B1...Bn, watch one
00883         std::memcpy(lits_+1, bodyLits, numBodies * sizeof(Literal));
00884         s.addWatch(~lits_[1+bodyToWatch], this, ((1+bodyToWatch)<<1)+1);
00885         lits_[1+bodyToWatch].watch();
00886 }
00887 
00888 void LoopFormula::destroy(Solver* s, bool detach) {
00889         if (s) {
00890                 if (detach) {
00891                         for (uint32 x = 1; x != end_-1; ++x) {
00892                                 if (lits_[x].watched()) {
00893                                         s->removeWatch(~lits_[x], this);
00894                                         lits_[x].clearWatch();
00895                                 }
00896                         }
00897                         if (lits_[end_-1].watched()) {
00898                                 lits_[end_-1].clearWatch();
00899                                 for (uint32 x = end_+1; x != size_; ++x) {
00900                                         s->removeWatch(~lits_[x], this);
00901                                         lits_[x].clearWatch();
00902                                 }
00903                         }
00904                 }
00905                 if (lits_[0].watched()) {
00906                         while (lits_[size_++].asUint() != 3u) { ; }
00907                 }
00908                 s->freeLearntBytes(sizeof(LoopFormula) + (size_ * sizeof(Literal)));
00909         }
00910         void* mem = static_cast<Constraint*>(this);
00911         this->~LoopFormula();
00912         Detail::free(mem);
00913 }
00914 
00915 
00916 void LoopFormula::addAtom(Literal atom, Solver& s) {
00917         act_.bumpAct();
00918         uint32 pos = size_++;
00919         assert(isSentinel(lits_[pos]));
00920         lits_[pos] = atom;
00921         lits_[pos].watch();
00922         s.addWatch( ~lits_[pos], this, (pos<<1)+0 );
00923         if (isSentinel(lits_[end_-1])) {
00924                 lits_[end_-1] = lits_[pos];
00925         }
00926 }
00927 
00928 void LoopFormula::updateHeuristic(Solver& s) {
00929         Literal saved = lits_[end_-1];
00930         for (uint32 x = end_+1; x != size_; ++x) {
00931                 lits_[end_-1] = lits_[x];
00932                 s.heuristic()->newConstraint(s, lits_+1, end_-1, Constraint_t::learnt_loop);
00933         }
00934         lits_[end_-1] = saved;
00935 }
00936 
00937 bool LoopFormula::watchable(const Solver& s, uint32 idx) {
00938         assert(!lits_[idx].watched());
00939         if (idx == end_-1) {
00940                 for (uint32 x = end_+1; x != size_; ++x) {
00941                         if (s.isFalse(lits_[x])) {
00942                                 lits_[idx] = lits_[x];
00943                                 return false;
00944                         }
00945                 }
00946         }
00947         return true;
00948 }
00949 
00950 bool LoopFormula::isTrue(const Solver& s, uint32 idx) {
00951         if (idx != end_-1) return s.isTrue(lits_[idx]);
00952         for (uint32 x = end_+1; x != size_; ++x) {
00953                 if (!s.isTrue(lits_[x])) {
00954                         lits_[end_-1] = lits_[x];
00955                         return false;
00956                 }
00957         }
00958         return true;
00959 }
00960 
00961 Constraint::PropResult LoopFormula::propagate(Solver& s, Literal, uint32& data) {
00962         if (isTrue(s, other_)) {          // ignore clause, as it is 
00963                 return PropResult(true, true);  // already satisfied
00964         }
00965         uint32  pos   = data >> 1;
00966         uint32  idx   = pos;
00967         if (pos > end_) {
00968                 // p is one of the atoms - move to active part
00969                 lits_[end_-1] = lits_[pos];
00970                 idx           = end_-1;
00971         }
00972         int     dir   = ((data & 1) << 1) - 1;
00973         int     bounds= 0;
00974         for (;;) {
00975                 for (idx+=dir;s.isFalse(lits_[idx]);idx+=dir) {;} // search non-false literal - sentinels guarantee termination
00976                 if (isSentinel(lits_[idx])) {             // Hit a bound,
00977                         if (++bounds == 2) {                    // both ends seen, clause is unit, false, or sat
00978                                 if (other_ == end_-1) {
00979                                         uint32 x = end_+1;
00980                                         for (; x != size_ && s.force(lits_[x], this);  ++x) { ; }
00981                                         return Constraint::PropResult(x == size_, true);  
00982                                 }
00983                                 else {
00984                                         return Constraint::PropResult(s.force(lits_[other_], this), true);  
00985                                 }
00986                         }
00987                         idx   = std::min(pos, end_-1);          // halfway through, restart search, but
00988                         dir   *= -1;                            // this time walk in the opposite direction.
00989                         data  ^= 1;                             // Save new direction of watch
00990                 }
00991                 else if (!lits_[idx].watched() && watchable(s, idx)) { // found a new watchable literal
00992                         if (pos > end_) {     // stop watching atoms
00993                                 lits_[end_-1].clearWatch();
00994                                 for (uint32 x = end_+1; x != size_; ++x) {
00995                                         if (x != pos) {
00996                                                 s.removeWatch(~lits_[x], this);
00997                                                 lits_[x].clearWatch();
00998                                         }
00999                                 }
01000                         }
01001                         lits_[pos].clearWatch();
01002                         lits_[idx].watch();
01003                         if (idx == end_-1) {  // start watching atoms
01004                                 for (uint32 x = end_+1; x != size_; ++x) {
01005                                         s.addWatch(~lits_[x], this, static_cast<uint32>(x << 1) + 0);
01006                                         lits_[x].watch();
01007                                 }
01008                         }
01009                         else {
01010                                 s.addWatch(~lits_[idx], this, static_cast<uint32>(idx << 1) + (dir==1));
01011                         }
01012                         return Constraint::PropResult(true, false);
01013                 } 
01014                 else if (lits_[idx].watched()) {          // Hit the other watched literal
01015                         other_  = idx;                          // Store it in other_
01016                 }
01017         }
01018 }
01019 
01020 // Body: all other bodies + active atom
01021 // Atom: all bodies
01022 void LoopFormula::reason(Solver& s, Literal p, LitVec& lits) {
01023         uint32 os = lits.size();
01024         // all relevant bodies
01025         for (uint32 x = 1; x != end_-1; ++x) {
01026                 if (lits_[x] != p) {
01027                         lits.push_back(~lits_[x]);
01028                 }
01029         }
01030         // if p is a body, add active atom
01031         if (other_ != end_-1) {
01032                 lits.push_back(~lits_[end_-1]);
01033         }
01034         act_.setLbd(s.updateLearnt(p, &lits[0]+os, &lits[0]+lits.size(), act_.lbd()));
01035         act_.bumpAct();
01036 }
01037 
01038 bool LoopFormula::minimize(Solver& s, Literal p, CCMinRecursive* rec) {
01039         act_.bumpAct();
01040         for (uint32 x = 1; x != end_-1; ++x) {
01041                 if (lits_[x] != p && !s.ccMinimize(~lits_[x], rec)) {
01042                         return false;
01043                 }
01044         }
01045         return other_ == end_-1
01046                 || s.ccMinimize(~lits_[end_-1], rec);
01047 }
01048 
01049 uint32 LoopFormula::size() const {
01050         return size_ - 3;
01051 }
01052 
01053 bool LoopFormula::locked(const Solver& s) const {
01054         if (other_ != end_-1) {
01055                 return s.isTrue(lits_[other_]) && s.reason(lits_[other_]) == this;
01056         }
01057         for (uint32 x = end_+1; x != size_; ++x) {
01058                 if (s.isTrue(lits_[x]) && s.reason(lits_[x]) == this) {
01059                         return true;
01060                 }
01061         }
01062         return false;
01063 }
01064 
01065 uint32 LoopFormula::isOpen(const Solver& s, const TypeSet& x, LitVec& freeLits) {
01066         if (!x.inSet(Constraint_t::learnt_loop) || (other_ != end_-1 && s.isTrue(lits_[other_]))) {
01067                 return 0;
01068         }
01069         for (uint32 x = 1; x != end_-1; ++x) {
01070                 if (s.isTrue(lits_[x])) {
01071                         other_ = x;
01072                         return 0;
01073                 }
01074                 else if (!s.isFalse(lits_[x])) { freeLits.push_back(lits_[x]); }
01075         }
01076         for (uint32 x = end_+1; x != size_; ++x) {
01077                 if      (s.value(lits_[x].var()) == value_free) { freeLits.push_back(lits_[x]); }
01078                 else if (s.isTrue(lits_[x]))                    { return 0; }
01079         }
01080         return Constraint_t::learnt_loop;
01081 }
01082 
01083 bool LoopFormula::simplify(Solver& s, bool) {
01084         assert(s.decisionLevel() == 0);
01085         typedef std::pair<uint32, uint32> WatchPos;
01086         bool      sat = false;          // is the constraint SAT?
01087         WatchPos  bodyWatches[2];       // old/new position of watched bodies
01088         uint32    bw  = 0;              // how many bodies are watched?
01089         uint32    j   = 1, i;
01090         // 1. simplify the set of bodies:
01091         // - search for a body that is true -> constraint is SAT
01092         // - remove all false bodies
01093         // - find the watched bodies
01094         for (i = 1; i != end_-1; ++i) {
01095                 assert( !s.isFalse(lits_[i]) || !lits_[i].watched() || s.isTrue(lits_[other_]) );
01096                 if (!s.isFalse(lits_[i])) {
01097                         sat |= s.isTrue(lits_[i]);
01098                         if (i != j) { lits_[j] = lits_[i]; }
01099                         if (lits_[j].watched()) { bodyWatches[bw++] = WatchPos(i, j); }
01100                         ++j;
01101                 }
01102         }
01103         uint32 newEnd = j + 1;
01104         j += 2;
01105         // 2. simplify the set of atoms:
01106         // - remove all determined atoms
01107         // - remove/update watches if necessary
01108         for (i = end_ + 1; i != size_; ++i) {
01109                 if (s.value(lits_[i].var()) == value_free) {
01110                         if (i != j) { lits_[j] = lits_[i]; }
01111                         if (lits_[j].watched()) {
01112                                 if (sat) {
01113                                         s.removeWatch(~lits_[j], this);
01114                                         lits_[j].clearWatch();
01115                                 }
01116                                 else if (i != j) {
01117                                         GenericWatch* w = s.getWatch(~lits_[j], this);
01118                                         assert(w);
01119                                         w->data = (j << 1) + 0;
01120                                 }
01121                         }
01122                         ++j;
01123                 }
01124                 else if (lits_[i].watched()) {
01125                         s.removeWatch(~lits_[i], this);
01126                         lits_[i].clearWatch();
01127                 }
01128         }
01129         if (j != size_ && !lits_[0].watched()) {
01130                 lits_[size_-1].asUint() = 3u;
01131                 lits_[0].watch();
01132         }
01133         size_         = j;
01134         end_          = newEnd;
01135         lits_[end_]   = Literal();
01136         lits_[end_-1] = lits_[end_+1];
01137         ClauseRep act = ClauseRep::create(lits_+1, end_-1, Constraint_t::learnt_loop);
01138         if (sat || size_ == end_ + 1 || (act.isImp() && s.allowImplicit(act))) {
01139                 for (i = 0; i != bw; ++i) {
01140                         s.removeWatch(~lits_[bodyWatches[i].second], this);
01141                         lits_[bodyWatches[i].second].clearWatch();
01142                 }
01143                 if (sat || size_ == end_+1) { return true; }
01144                 // replace constraint with short clauses
01145                 for (i = end_+1; i != size_; ++i) {
01146                         if (lits_[i].watched()) {
01147                                 s.removeWatch(~lits_[i], this);
01148                                 lits_[i].clearWatch();
01149                         }
01150                         lits_[end_-1] = lits_[i];
01151                         ClauseCreator::Result res = ClauseCreator::create(s, act, ClauseCreator::clause_no_add);
01152                         CLASP_FAIL_IF(!res.ok() || res.local, "LOOP MUST NOT CONTAIN AUX VARS!");
01153                 }
01154                 return true;
01155         }
01156         other_ = 1;
01157         for (i = 0; i != bw; ++i) {
01158                 if (bodyWatches[i].first != bodyWatches[i].second) {
01159                         GenericWatch* w  = s.getWatch(~lits_[bodyWatches[i].second], this);
01160                         assert(w);
01161                         w->data = (bodyWatches[i].second << 1) + (w->data&1);
01162                 }
01163         }
01164         return false;
01165 }
01166 }


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