Go to the documentation of this file.00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020 #include <clasp/cb_enumerator.h>
00021 #include <clasp/solver.h>
00022 #include <clasp/clause.h>
00023 #include <clasp/util/mutex.h>
00024 #include <stdio.h>
00025 #ifdef _MSC_VER
00026 #pragma warning (disable : 4996) // sprintf may be unfase
00027 #endif
00028 namespace Clasp {
00029
00031
00033 class CBConsequences::SharedConstraint {
00034 public:
00035 SharedConstraint() : current(0) {}
00036 SharedLiterals* fetch_if_neq(SharedLiterals* last) const {
00037 Clasp::lock_guard<Clasp::spin_mutex> lock(mutex);
00038 return last != current ? current->share() : 0;
00039 }
00040 void release(SharedLiterals* newLits) {
00041 SharedLiterals* old = current;
00042 { Clasp::lock_guard<Clasp::spin_mutex> lock(mutex); current = newLits; }
00043 if (old) { old->release(); }
00044 }
00045 SharedLiterals* current;
00046 mutable Clasp::spin_mutex mutex;
00047 };
00049
00051 class CBConsequences::CBFinder : public EnumerationConstraint {
00052 public:
00053 typedef CBConsequences::SharedConstraint SharedCon;
00054 typedef Solver::ConstraintDB ConstraintDB;
00055 typedef SharedLiterals SharedLits;
00056 CBFinder(Solver& s, MinimizeConstraint* min, SharedCon* sh)
00057 : EnumerationConstraint(s, min), shared(sh), last(0) {}
00058
00059 Constraint* cloneAttach(Solver& s) { return new CBFinder(s, cloneMinimizer(s), shared); }
00060 void doCommitModel(Enumerator& ctx, Solver& s) { static_cast<CBConsequences&>(ctx).addCurrent(s, current, s.model); }
00061 void destroy(Solver* s, bool detach);
00062 bool doUpdate(Solver& s);
00063 void pushLocked(Solver& s, ClauseHead* h);
00064 LitVec current;
00065 SharedCon* shared;
00066 SharedLits* last;
00067 ConstraintDB locked;
00068 };
00070
00072 CBConsequences::CBConsequences(Consequences_t type)
00073 : Enumerator()
00074 , shared_(0)
00075 , type_(type) {}
00076
00077 Enumerator* EnumOptions::createConsEnumerator(const EnumOptions& opts) {
00078 return new CBConsequences(opts.type == enum_brave ? CBConsequences::brave_consequences : CBConsequences::cautious_consequences);
00079 }
00080 CBConsequences::~CBConsequences() {
00081 delete shared_;
00082 }
00083 EnumerationConstraint* CBConsequences::doInit(SharedContext& ctx, MinimizeConstraint* min, int) {
00084 cons_.clear();
00085 const SymbolTable& index = ctx.symbolTable();
00086 if (index.type() == SymbolTable::map_direct) {
00087 for (Var v = 1, end = index.size(); v < end; ++v) {
00088 if (!ctx.marked(posLit(v))) {
00089 cons_.push_back(posLit(v));
00090 ctx.mark(cons_.back());
00091 }
00092 }
00093 }
00094 else {
00095 for (SymbolTable::const_iterator it = index.begin(); it != index.end(); ++it) {
00096 if (!it->second.name.empty() && !ctx.marked(it->second.lit)) {
00097 cons_.push_back(it->second.lit);
00098 ctx.mark(cons_.back());
00099 }
00100 }
00101 }
00102 uint32 m = (type_ == cautious_consequences);
00103 for (LitVec::iterator it = cons_.begin(), end = cons_.end(); it != end; ++it) {
00104 ctx.setFrozen(it->var(), true);
00105 ctx.unmark(it->var());
00106 it->asUint() |= m;
00107 }
00108 delete shared_;
00109 shared_ = ctx.concurrency() > 1 ? new SharedConstraint() : 0;
00110 setIgnoreSymmetric(true);
00111 return new CBFinder(*ctx.master(), min, shared_);
00112 }
00113 void CBConsequences::addCurrent(Solver& s, LitVec& con, ValueVec& m) {
00114 con.clear();
00115 con.push_back(~s.sharedContext()->stepLiteral());
00116 for (LitVec::iterator it = cons_.begin(), end = cons_.end(); it != end; ++it) {
00117 m[it->var()] = 0;
00118 }
00119 if (type_ == brave_consequences) {
00120 for (LitVec::iterator it = cons_.begin(), end = cons_.end(); it != end; ++it) {
00121 Literal& p = *it;
00122 if (s.isTrue(p) || p.watched()) {
00123 m[p.var()] |= trueValue(p);
00124 p.watch();
00125 }
00126 else if (s.level(p.var())) {
00127 con.push_back(p);
00128 }
00129 }
00130 }
00131 else if (type_ == cautious_consequences) {
00132 for (LitVec::iterator it = cons_.begin(), end = cons_.end(); it != end; ++it) {
00133 Literal& p = *it;
00134 if (!s.isTrue(p) || !p.watched()) {
00135 m[p.var()] &= ~trueValue(p);
00136 p.clearWatch();
00137 }
00138 else {
00139 if (s.level(p.var())) { con.push_back(~p); }
00140 m[p.var()] |= trueValue(p);
00141 }
00142 }
00143 }
00144 if (con.empty()) { con.push_back(negLit(0)); }
00145 if (shared_) {
00146 shared_->release(SharedLiterals::newShareable(con, Constraint_t::learnt_other, 1));
00147 }
00148 }
00150
00152 void CBConsequences::CBFinder::destroy(Solver* s, bool detach) {
00153 while (!locked.empty()) {
00154 static_cast<ClauseHead*>(locked.back())->destroy(s, detach);
00155 locked.pop_back();
00156 }
00157 EnumerationConstraint::destroy(s, detach);
00158 }
00159 void CBConsequences::CBFinder::pushLocked(Solver& s, ClauseHead* c) {
00160 for (ClauseHead* h; !locked.empty() && !(h = static_cast<ClauseHead*>(locked.back()))->locked(s);) {
00161 h->destroy(&s, true);
00162 locked.pop_back();
00163 }
00164 locked.push_back(c);
00165 }
00166 bool CBConsequences::CBFinder::doUpdate(Solver& s) {
00167 ClauseCreator::Result ret;
00168 uint32 flags = ClauseCreator::clause_explicit|ClauseCreator::clause_no_add;
00169 if (!shared) {
00170 ret = !current.empty() ? ClauseCreator::create(s, current, flags, ClauseInfo(Constraint_t::learnt_other)) : ClauseCreator::Result();
00171 }
00172 else if (SharedLiterals* x = shared->fetch_if_neq(last)) {
00173 last = x;
00174 ret = ClauseCreator::integrate(s, x, flags);
00175 }
00176 if (ret.local) { pushLocked(s, ret.local); }
00177 current.clear();
00178 return ret.ok();
00179 }
00180 }