00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020 #ifdef _MSC_VER
00021 #pragma warning(disable : 4996) // std::copy was declared deprecated
00022 #endif
00023
00024 #include <clasp/unfounded_check.h>
00025 #include <clasp/clause.h>
00026 #include <algorithm>
00027 #include <cmath>
00028 namespace Clasp {
00030
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045
00046
00047
00048
00049
00050
00051
00052
00053
00054
00055
00056
00057
00058
00059
00060
00061
00062
00063
00064
00065
00066
00067
00068
00069
00070
00071
00072 DefaultUnfoundedCheck::DefaultUnfoundedCheck()
00073 : solver_(0)
00074 , graph_(0)
00075 , mini_(0)
00076 , reasons_(0)
00077 , strategy_(common_reason) {
00078 mini_.release();
00079 }
00080 DefaultUnfoundedCheck::~DefaultUnfoundedCheck() {
00081 for (ExtVec::size_type i = 0; i != extended_.size(); ++i) {
00082 ::operator delete(extended_[i]);
00083 }
00084 delete [] reasons_;
00085 }
00087
00089 void DefaultUnfoundedCheck::addWatch(Literal p, uint32 data, WatchType type) {
00090 assert(data < varMax);
00091 solver_->addWatch(p, this, static_cast<uint32>((data << 2) | type));
00092 }
00093
00094
00095
00096
00097
00098 bool DefaultUnfoundedCheck::init(Solver& s) {
00099 assert(!graph_ || s.sharedContext()->sccGraph.get() == graph_);
00100 if (s.sharedContext()->sccGraph.get() == 0) {
00101 s.removePost(this);
00102 return true;
00103 }
00104 solver_ = &s;
00105 graph_ = s.sharedContext()->sccGraph.get();
00106 strategy_ = s.strategy.search != SolverStrategies::no_learning ? static_cast<ReasonStrategy>(s.configuration().loopRep) : no_reason;
00107 if (strategy_ == only_reason) {
00108 delete [] reasons_;
00109 reasons_ = new LitVec[solver_->numVars()];
00110 }
00111
00112 while (findUfs(s, false) != ufs_none) {
00113 while (!ufs_.empty()) {
00114 if (!s.force(~graph_->getAtom(ufs_.front()).lit, 0)) { return false; }
00115 atoms_[ufs_.pop_ret()].ufs = 0;
00116 }
00117 }
00118 AtomVec::size_type startAtom = atoms_.size();
00119
00120 atoms_.resize(graph_->numAtoms());
00121 AtomData& sentinel = atoms_[SharedDependencyGraph::sentinel_atom];
00122 sentinel.resurrectSource();
00123 sentinel.todo = 1;
00124 sentinel.ufs = 1;
00125
00126 for (uint32 i = (uint32)bodies_.size(); i != graph_->numBodies(); ++i) {
00127 bodies_.push_back(BodyData());
00128 BodyPtr n(getBody(i));
00129 if (!n.node->extended()) {
00130 initBody(n);
00131 }
00132 else {
00133 initExtBody(n);
00134 }
00135
00136 addWatch(~n.node->lit, n.id, watch_source_false);
00137 }
00138
00139 propagateSource();
00140 for (AtomVec::size_type i = startAtom, end = atoms_.size(); i != end; ++i) {
00141 const AtomNode& a = graph_->getAtom(NodeId(i));
00142 if (!atoms_[i].hasSource() && !solver_->force(~a.lit, 0)) {
00143 return false;
00144 }
00145 if (a.inChoice()) {
00146 addWatch(~a.lit, NodeId(i), watch_head_false);
00147 }
00148 }
00149 if (graph_->numNonHcfs() != 0) {
00150 mini_ = new MinimalityCheck(s.searchConfig().fwdCheck);
00151 }
00152 return true;
00153 }
00154
00155
00156 void DefaultUnfoundedCheck::initBody(const BodyPtr& n) {
00157 assert(n.id < bodies_.size());
00158 BodyData& data = bodies_[n.id];
00159
00160
00161 data.lower_or_ext = n.node->num_preds();
00162 initSuccessors(n, data.lower_or_ext);
00163 }
00164
00165
00166
00167 void DefaultUnfoundedCheck::initExtBody(const BodyPtr& n) {
00168 assert(n.id < bodies_.size() && n.node->extended());
00169 BodyData& data = bodies_[n.id];
00170 uint32 preds = n.node->num_preds();
00171 ExtData* extra = new (::operator new(sizeof(ExtData) + (ExtData::flagSize(preds)*sizeof(uint32)))) ExtData(n.node->ext_bound(), preds);
00172
00173 InitExtWatches addWatches = { this, &n, extra };
00174 graph_->visitBodyLiterals(*n.node, addWatches);
00175
00176 data.lower_or_ext = (uint32)extended_.size();
00177 extended_.push_back(extra);
00178 initSuccessors(n, extra->lower);
00179 }
00180
00181
00182 void DefaultUnfoundedCheck::initSuccessors(const BodyPtr& n, weight_t lower) {
00183 if (!solver_->isFalse(n.node->lit)) {
00184 for (const NodeId* x = n.node->heads_begin(); x != n.node->heads_end(); ++x) {
00185 const AtomNode& a = graph_->getAtom(*x);
00186 if (a.scc != n.node->scc || lower <= 0) {
00187 setSource(*x, n);
00188 }
00189 }
00190 }
00191 }
00192
00193
00194 void DefaultUnfoundedCheck::addExtWatch(Literal p, const BodyPtr& B, uint32 data) {
00195 addWatch(p, static_cast<uint32>(watches_.size()), watch_subgoal_false);
00196 ExtWatch w = { B.id, data };
00197 watches_.push_back(w);
00198 }
00200
00202 void DefaultUnfoundedCheck::reason(Solver&, Literal p, LitVec& r) {
00203 LitVec::const_iterator it, end;
00204 if (!activeClause_.empty() && activeClause_[0] == p) {
00205 it = activeClause_.begin()+1;
00206 end = activeClause_.end();
00207 }
00208 else {
00209 assert(strategy_ == only_reason && reasons_);
00210 it = reasons_[p.var()-1].begin();
00211 end = reasons_[p.var()-1].end();
00212 }
00213 for (; it != end; ++it) r.push_back( ~*it );
00214 }
00215
00216 bool DefaultUnfoundedCheck::propagateFixpoint(Solver& s, PostPropagator* ctx) {
00217 bool checkMin = ctx == 0 && mini_.get() && mini_->partialCheck(s.decisionLevel());
00218 for (UfsType t; (t = findUfs(s, checkMin)) != ufs_none; ) {
00219 if (!falsifyUfs(t)) {
00220 resetTodo();
00221 return false;
00222 }
00223 }
00224 return true;
00225 }
00226
00227 void DefaultUnfoundedCheck::reset() {
00228 assert(loopAtoms_.empty() && sourceQ_.empty() && ufs_.empty() && todo_.empty());
00229
00230
00231
00232 if (solver_->decisionLevel()) {
00233 invalidQ_.clear();
00234 }
00235 }
00236 bool DefaultUnfoundedCheck::valid(Solver& s) {
00237 if (!mini_.get() || findNonHcfUfs(s) == ufs_none) { return true; }
00238 falsifyUfs(ufs_non_poly);
00239 return false;
00240 }
00241 bool DefaultUnfoundedCheck::isModel(Solver& s) {
00242 return DefaultUnfoundedCheck::valid(s);
00243 }
00245
00247
00248 void DefaultUnfoundedCheck::propagateSource() {
00249 for (LitVec::size_type i = 0; i < sourceQ_.size(); ++i) {
00250 NodeId atom = sourceQ_[i];
00251 if (atoms_[atom].hasSource()) {
00252
00253 graph_->getAtom(atom).visitSuccessors(AddSource(this));
00254 }
00255 else {
00256 graph_->getAtom(atom).visitSuccessors(RemoveSource(this));
00257 }
00258 }
00259 sourceQ_.clear();
00260 }
00261
00262
00263 void DefaultUnfoundedCheck::updateSource(AtomData& atom, const BodyPtr& n) {
00264 if (atom.watch() != AtomData::nill_source) {
00265 --bodies_[atom.watch()].watches;
00266 }
00267 atom.setSource(n.id);
00268 ++bodies_[n.id].watches;
00269 }
00270
00271
00272 void DefaultUnfoundedCheck::AddSource::operator()(NodeId bodyId, uint32 idx) const {
00273 BodyPtr n(self->getBody(bodyId));
00274 ExtData* ext = self->extended_[self->bodies_[bodyId].lower_or_ext];
00275 if (ext->lower > 0 || self->bodies_[n.id].watches == 0) {
00276
00277 ext->addToWs(idx, n.node->pred_weight(idx, false));
00278 }
00279 if (!self->solver_->isFalse(n.node->lit) && ext->lower <= 0) {
00280
00281 self->forwardSource(n);
00282 }
00283 }
00284
00285 void DefaultUnfoundedCheck::RemoveSource::operator()(NodeId bodyId, uint32 idx) const {
00286 BodyPtr n(self->getBody(bodyId));
00287 ExtData* ext = self->extended_[self->bodies_[bodyId].lower_or_ext];
00288 ext->removeFromWs(idx, n.node->pred_weight(idx, false));
00289 if (ext->lower > 0 && self->bodies_[n.id].watches > 0) {
00290
00291
00292 self->forwardUnsource(n, true);
00293 }
00294 }
00295
00296
00297 void DefaultUnfoundedCheck::forwardSource(const BodyPtr& n) {
00298 for (const NodeId* x = n.node->heads_begin(); x != n.node->heads_end(); ++x) {
00299 setSource(*x, n);
00300 }
00301 }
00302
00303
00304 void DefaultUnfoundedCheck::forwardUnsource(const BodyPtr& n, bool add) {
00305 for (const NodeId* x = n.node->heads_begin(); x != n.node->heads_end() && graph_->getAtom(*x).scc == n.node->scc; ++x) {
00306 if (atoms_[*x].hasSource() && atoms_[*x].watch() == n.id) {
00307 atoms_[*x].markSourceInvalid();
00308 sourceQ_.push_back(*x);
00309 }
00310 if (add && atoms_[*x].watch() == n.id) {
00311 pushTodo(*x);
00312 }
00313 }
00314 }
00315
00316
00317
00318
00319 void DefaultUnfoundedCheck::setSource(NodeId head, const BodyPtr& body) {
00320 assert(!solver_->isFalse(body.node->lit));
00321
00322
00323
00324
00325 if (!atoms_[head].hasSource() && !solver_->isFalse(graph_->getAtom(head).lit)) {
00326 updateSource(atoms_[head], body);
00327 sourceQ_.push_back(head);
00328 }
00329 }
00330
00331
00332
00333
00334 void DefaultUnfoundedCheck::removeSource(NodeId bodyId) {
00335 const BodyNode& body = graph_->getBody(bodyId);
00336 for (const NodeId* x = body.heads_begin(); x != body.heads_end(); ++x) {
00337 if (atoms_[*x].watch() == bodyId) {
00338 if (atoms_[*x].hasSource()) {
00339 atoms_[*x].markSourceInvalid();
00340 sourceQ_.push_back(*x);
00341 }
00342 pushTodo(*x);
00343 }
00344 }
00345 propagateSource();
00346 }
00347
00349
00351 void DefaultUnfoundedCheck::updateAssignment(Solver& s) {
00352 assert(sourceQ_.empty() && ufs_.empty() && pickedExt_.empty());
00353 for (VarVec::const_iterator it = invalidQ_.begin(), end = invalidQ_.end(); it != end; ++it) {
00354 uint32 index = (*it) >> 2;
00355 uint32 type = (*it) & 3u;
00356 if (type == watch_source_false) {
00357
00358 removeSource(index);
00359 }
00360 else if (type == watch_head_false) {
00361
00362
00363
00364 if (atoms_[index].hasSource() && !s.isFalse(graph_->getBody(atoms_[index].watch()).lit)) {
00365 atoms_[index].markSourceInvalid();
00366 graph_->getAtom(index).visitSuccessors(RemoveSource(this, true));
00367 propagateSource();
00368 }
00369 }
00370 else if (type == watch_head_true) {
00371
00372 }
00373 else if (type == watch_subgoal_false) {
00374 assert(index < watches_.size());
00375 const ExtWatch& w = watches_[index];
00376 const BodyNode& body = graph_->getBody(w.bodyId);
00377 ExtData* ext = extended_[bodies_[w.bodyId].lower_or_ext];
00378 ext->removeFromWs(w.data>>1, body.pred_weight(w.data>>1, test_bit(w.data, 0) != 0));
00379 if (ext->lower > 0 && bodies_[w.bodyId].watches && !bodies_[w.bodyId].picked && !s.isFalse(body.lit)) {
00380
00381
00382 removeSource(w.bodyId);
00383 pickedExt_.push_back(w.bodyId);
00384 bodies_[w.bodyId].picked = 1;
00385 }
00386 }
00387 }
00388 for (VarVec::size_type i = 0, end = pickedExt_.size(); i != end; ++i) {
00389 bodies_[pickedExt_[i]].picked = 0;
00390 }
00391 pickedExt_.clear();
00392 invalidQ_.clear();
00393 }
00394
00395 DefaultUnfoundedCheck::UfsType DefaultUnfoundedCheck::findUfs(Solver& s, bool checkMin) {
00396
00397 updateAssignment(s);
00398
00399 while (!todo_.empty()) {
00400 NodeId head = todo_.pop_ret();
00401 atoms_[head].todo = 0;
00402 if (!atoms_[head].hasSource() && !s.isFalse(graph_->getAtom(head).lit) && !findSource(head)) {
00403 return ufs_poly;
00404 }
00405 assert(sourceQ_.empty());
00406 }
00407 todo_.clear();
00408 return !checkMin ? ufs_none : findNonHcfUfs(s);
00409 }
00410
00411
00412
00413
00414
00415 bool DefaultUnfoundedCheck::findSource(NodeId headId) {
00416 assert(ufs_.empty() && invalidQ_.empty());
00417 const NodeId* bodyIt, *bodyEnd;
00418 uint32 newSource = 0;
00419 pushUfs(headId);
00420 while (!ufs_.empty()) {
00421 headId = ufs_.pop_ret();
00422 AtomData& head = atoms_[headId];
00423 if (!head.hasSource()) {
00424 const AtomNode& headNode = graph_->getAtom(headId);
00425 for (bodyIt = headNode.bodies_begin(), bodyEnd = headNode.bodies_end(); bodyIt != bodyEnd; ++bodyIt) {
00426 BodyPtr bodyNode(getBody(*bodyIt));
00427 if (!solver_->isFalse(bodyNode.node->lit)) {
00428 if (bodyNode.node->scc != headNode.scc || isValidSource(bodyNode)) {
00429 head.ufs = 0;
00430 setSource(headId, bodyNode);
00431 propagateSource();
00432 ++newSource;
00433 break;
00434 }
00435 else { addUnsourced(bodyNode); }
00436 }
00437 }
00438 if (!head.hasSource()) {
00439 invalidQ_.push_back(headId);
00440 }
00441 }
00442 else {
00443 ++newSource;
00444 head.ufs = 0;
00445 }
00446 }
00447 ufs_.rewind();
00448 if (newSource != 0) {
00449
00450
00451 uint32 visited = ufs_.vec.size();
00452 ufs_.clear();
00453 if (visited != newSource) {
00454
00455 for (VarVec::iterator it = invalidQ_.begin(), end = invalidQ_.end(); it != end; ++it) {
00456 if ( (atoms_[*it].ufs = (1u - atoms_[*it].validS)) == 1 ) { ufs_.push(*it); }
00457 }
00458 }
00459 }
00460 invalidQ_.clear();
00461 return ufs_.empty();
00462 }
00463
00464
00465 bool DefaultUnfoundedCheck::isValidSource(const BodyPtr& n) {
00466 if (!n.node->extended()) {
00467 return bodies_[n.id].lower_or_ext == 0;
00468 }
00469 ExtData* ext = extended_[bodies_[n.id].lower_or_ext];
00470 if (ext->lower > 0) {
00471
00472
00473
00474
00475
00476
00477 const uint32 inc = n.node->pred_inc();
00478 const NodeId* x = n.node->preds();
00479 uint32 p = 0;
00480 for (; *x != idMax; x += inc, ++p) {
00481 if (atoms_[*x].hasSource() && !ext->inWs(p) && !solver_->isFalse(graph_->getAtom(*x).lit)) {
00482 ext->addToWs(p, n.node->pred_weight(p, false));
00483 }
00484 }
00485
00486
00487
00488 for (++x; *x != idMax; x += inc, ++p) {
00489 if (!solver_->isFalse(Literal::fromRep(*x)) && !ext->inWs(p)) {
00490 ext->addToWs(p, n.node->pred_weight(p, true));
00491 }
00492 }
00493 }
00494 return ext->lower <= 0;
00495 }
00496
00497
00498
00499 void DefaultUnfoundedCheck::addUnsourced(const BodyPtr& n) {
00500 const uint32 inc = n.node->pred_inc();
00501 for (const NodeId* x = n.node->preds(); *x != idMax; x += inc) {
00502 if (!atoms_[*x].hasSource() && !solver_->isFalse(graph_->getAtom(*x).lit)) {
00503 pushUfs(*x);
00504 }
00505 }
00506 }
00507
00508
00509 bool DefaultUnfoundedCheck::falsifyUfs(UfsType t) {
00510 activeClause_.clear();
00511 while (!ufs_.empty()) {
00512 Literal a = graph_->getAtom(ufs_.front()).lit;
00513 if (!solver_->isFalse(a) && !(assertAtom(a, t) && solver_->propagateUntil(this))) {
00514 if (t == ufs_non_poly) {
00515 mini_->schedNext(solver_->decisionLevel(), false);
00516 }
00517 break;
00518 }
00519 assert(solver_->isFalse(a));
00520 atoms_[ufs_.pop_ret()].ufs = 0;
00521 }
00522 if (!loopAtoms_.empty()) {
00523 createLoopFormula();
00524 }
00525 resetUfs();
00526 activeClause_.clear();
00527 return !solver_->hasConflict();
00528 }
00529
00530
00531 bool DefaultUnfoundedCheck::assertAtom(Literal a, UfsType t) {
00532 if (solver_->isTrue(a) || strategy_ == distinct_reason || activeClause_.empty()) {
00533
00534
00535
00536
00537 if (!loopAtoms_.empty()) {
00538 createLoopFormula();
00539 }
00540 activeClause_.assign(1, ~a);
00541 computeReason(t);
00542 }
00543 activeClause_[0] = ~a;
00544 bool noClause = solver_->isTrue(a) || strategy_ == no_reason || strategy_ == only_reason || (strategy_ == shared_reason && activeClause_.size() > 3);
00545 if (noClause) {
00546 if (!solver_->force(~a, this)) { return false; }
00547 if (strategy_ == only_reason) { reasons_[a.var()-1].assign(activeClause_.begin()+1, activeClause_.end()); }
00548 else if (strategy_ != no_reason){ loopAtoms_.push_back(~a); }
00549 return true;
00550 }
00551 else {
00552 return ClauseCreator::create(*solver_, activeClause_, ClauseCreator::clause_no_prepare, info_).ok();
00553 }
00554 }
00555 void DefaultUnfoundedCheck::createLoopFormula() {
00556 assert(activeClause_.size() > 3);
00557 if (loopAtoms_.size() == 1) {
00558 activeClause_[0] = loopAtoms_[0];
00559 Constraint* ante = ClauseCreator::create(*solver_, activeClause_, ClauseCreator::clause_no_prepare, info_).local;
00560 assert(ante != 0 && solver_->isTrue(loopAtoms_[0]) && solver_->reason(loopAtoms_[0]) == this);
00561 solver_->setReason(loopAtoms_[0], ante);
00562 }
00563 else {
00564 Activity act(info_.activity(), info_.lbd());
00565 LoopFormula* lf = LoopFormula::newLoopFormula(*solver_, &activeClause_[1], (uint32)activeClause_.size() - 1, (uint32)0, (uint32)loopAtoms_.size(), act);
00566 solver_->addLearnt(lf, lf->size(), Constraint_t::learnt_loop);
00567 for (VarVec::size_type i = 0; i < loopAtoms_.size(); ++i) {
00568 assert(solver_->isTrue(loopAtoms_[i]) && solver_->reason(loopAtoms_[i]) == this);
00569 solver_->setReason(loopAtoms_[i], lf);
00570 lf->addAtom(loopAtoms_[i], *solver_);
00571 }
00572 lf->updateHeuristic(*solver_);
00573 }
00574 loopAtoms_.clear();
00575 }
00576
00577
00578 void DefaultUnfoundedCheck::computeReason(UfsType t) {
00579 if (strategy_ == no_reason) { return; }
00580 uint32 ufsScc = graph_->getAtom(ufs_.front()).scc;
00581 for (VarVec::size_type i = ufs_.qFront; i != ufs_.vec.size(); ++i) {
00582 const AtomNode& atom = graph_->getAtom(ufs_.vec[i]);
00583 if (!solver_->isFalse(atom.lit)) {
00584 assert(atom.scc == ufsScc);
00585 for (const NodeId* x = atom.bodies_begin(); x != atom.bodies_end(); ++x) {
00586 BodyPtr body(getBody(*x));
00587 if (t == ufs_poly || !body.node->delta()){ addIfReason(body, ufsScc); }
00588 else { addDeltaReason(body, ufsScc); }
00589 }
00590 }
00591 }
00592 for (VarVec::size_type i = 0; i != pickedExt_.size(); ++i) { bodies_[pickedExt_[i]].picked = 0; }
00593 pickedExt_.clear();
00594 info_ = ClauseInfo(Constraint_t::learnt_loop);
00595 uint32 rc = !solver_->isFalse(activeClause_[0]) && activeClause_.size() > 100 && activeClause_.size() > (solver_->decisionLevel() * 10);
00596 uint32 dl = solver_->finalizeConflictClause(activeClause_, info_, rc);
00597 uint32 cDL= solver_->decisionLevel();
00598 assert((t == ufs_non_poly || dl == cDL) && "Loop nogood must contain a literal from current DL!");
00599 if (dl < cDL && (dl = solver_->undoUntil(dl, false)) < cDL) {
00600
00601 invalidQ_.clear();
00602 for (PostPropagator* n = this->next; n; n = n->next) { n->reset(); }
00603 }
00604 }
00605
00606 void DefaultUnfoundedCheck::addDeltaReason(const BodyPtr& n, uint32 uScc) {
00607 if (bodies_[n.id].picked != 0) return;
00608 uint32 bodyAbst = solver_->isFalse(n.node->lit) ? solver_->level(n.node->lit.var()) : solver_->decisionLevel() + 1;
00609 for (const NodeId* x = n.node->heads_begin(); x != n.node->heads_end(); ++x) {
00610 if (*x != SharedDependencyGraph::sentinel_atom) {
00611 if (graph_->getAtom(*x).scc == uScc) {
00612 addIfReason(n, uScc);
00613 }
00614 continue;
00615 }
00616 else {
00617 uint32 reasonAbst= bodyAbst;
00618 Literal reasonLit = n.node->lit;
00619 bool inUfs = false;
00620 Literal aLit;
00621 for (++x; *x; ++x) {
00622 if (atoms_[*x].ufs == 1) {
00623 inUfs = true;
00624 }
00625 else if (solver_->isTrue(aLit = graph_->getAtom(*x).lit) && solver_->level(aLit.var()) < reasonAbst) {
00626 reasonLit = ~aLit;
00627 reasonAbst = solver_->level(reasonLit.var());
00628 }
00629 }
00630 if (inUfs && reasonAbst && reasonAbst <= solver_->decisionLevel()) {
00631 addReasonLit(reasonLit);
00632 }
00633 }
00634 }
00635 bodies_[n.id].picked = 1;
00636 pickedExt_.push_back(n.id);
00637 }
00638
00639 void DefaultUnfoundedCheck::addIfReason(const BodyPtr& n, uint32 uScc) {
00640 if (solver_->isFalse(n.node->lit)) {
00641 if (n.node->scc != uScc) {
00642 addReasonLit(n.node->lit);
00643 }
00644 else if (!solver_->seen(n.node->lit)) {
00645 if (!n.node->extended()) {
00646
00647 for (const NodeId* x = n.node->preds(); *x != idMax; ++x) {
00648 if (atoms_[*x].ufs && !solver_->isFalse(graph_->getAtom(*x).lit)) {
00649
00650 return;
00651 }
00652 }
00653 addReasonLit(n.node->lit);
00654 }
00655 else if (bodies_[n.id].picked == 0) {
00656 bodies_[n.id].picked = 1;
00657 pickedExt_.push_back(n.id);
00658
00659
00660 ExtData* ext = extended_[bodies_[n.id].lower_or_ext];
00661 weight_t temp = ext->lower;
00662 const NodeId* x = n.node->preds();
00663 const uint32 inc = n.node->pred_inc();
00664 uint32 p = 0;
00665 for (; *x != idMax; x += inc, ++p) {
00666 if (!ext->inWs(p) && (atoms_[*x].ufs == 0 || solver_->isFalse(graph_->getAtom(*x).lit))) {
00667 if ( (temp -= n.node->pred_weight(p, false)) <= 0 ) {
00668 addReasonLit(n.node->lit);
00669 return;
00670 }
00671 }
00672 }
00673 for (++x; *x != idMax; x += inc, ++p) {
00674 if (!ext->inWs(p) && (temp -= n.node->pred_weight(p, true)) <= 0) {
00675 addReasonLit(n.node->lit);
00676 return;
00677 }
00678 }
00679 }
00680 }
00681 }
00682 else if (n.node->scc == uScc && n.node->extended() && bodies_[n.id].picked == 0) {
00683 bodies_[n.id].picked = 1;
00684 pickedExt_.push_back(n.id);
00685
00686 AddReasonLit addFalseLits = { this };
00687 graph_->visitBodyLiterals(*n.node, addFalseLits);
00688 }
00689 }
00690
00691 void DefaultUnfoundedCheck::addReasonLit(Literal p) {
00692 if (!solver_->seen(p)) {
00693 solver_->markSeen(p);
00694 solver_->markLevel(solver_->level(p.var()));
00695 activeClause_.push_back(p);
00696 if (solver_->level(p.var()) > solver_->level(activeClause_[1].var())) {
00697 std::swap(activeClause_[1], activeClause_.back());
00698 }
00699 }
00700 }
00701
00703
00705 DefaultUnfoundedCheck::UfsType DefaultUnfoundedCheck::findNonHcfUfs(Solver& s) {
00706 assert(invalidQ_.empty() && loopAtoms_.empty());
00707 for (SharedDependencyGraph::NonHcfIter it = graph_->nonHcfBegin(), end = graph_->nonHcfEnd(); it != end; ++it) {
00708 s.stats.addTest(s.numFreeVars() != 0);
00709 it->second->assumptionsFromAssignment(s, loopAtoms_);
00710 if (!it->second->test(it->first, s, loopAtoms_, invalidQ_) || s.hasConflict()) {
00711 uint32 pos = 0, minDL = 0;
00712 for (VarVec::const_iterator it = invalidQ_.begin(), end = invalidQ_.end(); it != end; ++it) {
00713 if (s.isTrue(graph_->getAtom(*it).lit) && s.level(graph_->getAtom(*it).lit.var()) < minDL) {
00714 minDL = s.level(graph_->getAtom(*it).lit.var());
00715 pos = (uint32)ufs_.vec.size();
00716 }
00717 pushUfs(*it);
00718 }
00719 if (pos) {
00720 std::swap(ufs_.vec.front(), ufs_.vec[pos]);
00721 }
00722 invalidQ_.clear();
00723 loopAtoms_.clear();
00724 return ufs_non_poly;
00725 }
00726 loopAtoms_.clear();
00727 }
00728 mini_->schedNext(s.decisionLevel(), true);
00729 return ufs_none;
00730 }
00731
00732 DefaultUnfoundedCheck::MinimalityCheck::MinimalityCheck(const FwdCheck& afwd) : fwd(afwd), high(UINT32_MAX), low(0), next(0) {
00733 if (fwd.highPct > 100) { fwd.highPct = 100; }
00734 if (fwd.initHigh != 0) { high = fwd.initHigh; }
00735 }
00736
00737 bool DefaultUnfoundedCheck::MinimalityCheck::partialCheck(uint32 level) {
00738 if (level < low) {
00739 next -= (low - level);
00740 low = level;
00741 }
00742 return !next || next == level;
00743 }
00744
00745 void DefaultUnfoundedCheck::MinimalityCheck::schedNext(uint32 level, bool ok) {
00746 low = 0;
00747 next = UINT32_MAX;
00748 if (!ok) {
00749 high = level;
00750 next = 0;
00751 }
00752 else if (fwd.highPct != 0) {
00753 double p = fwd.highPct / 100.0;
00754 high = std::max(high, level);
00755 low = level;
00756 if (low >= high && fwd.incHigh) {
00757 high = (uint32)std::ceil(low + (low * p));
00758 }
00759 next = low + (uint32)std::ceil((high - low) * p);
00760 }
00761 }
00762 }