00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020 #include <clasp/asp_preprocessor.h>
00021 #include <clasp/logic_program.h>
00022 #include <clasp/shared_context.h>
00023 namespace Clasp { namespace Asp {
00025
00026
00027
00028
00030 bool Preprocessor::preprocessSimple() {
00031 if (!prg_->propagate(true)) { return false; }
00032 uint32 startVar = prg_->ctx()->numVars() + 1;
00033
00034 VarVec& supported = prg_->getSupportedBodies(true);
00035 for (VarVec::size_type i = 0; i < supported.size(); ++i) {
00036 PrgBody* b = prg_->getBody(supported[i]);
00037
00038 if (!b->simplify(*prg_, false)) { return false; }
00039 if (b->var() < startVar) { b->assignVar(*prg_); }
00040
00041 if (!addHeadsToUpper(b)) { return false; }
00042 }
00043 return prg_->propagate();
00044 }
00045
00046 bool Preprocessor::addHeadToUpper(PrgHead* head, PrgEdge h, PrgEdge support) {
00047 assert(head->relevant() && !head->inUpper());
00048 head->simplifySupports(*prg_, false);
00049 head->assignVar(*prg_, support);
00050 head->clearSupports();
00051 head->setInUpper(true);
00052 if (head->isAtom()) {
00053 return propagateAtomVar(h.node(), static_cast<PrgAtom*>(head), support);
00054 }
00055
00056 assert(h.isDisj());
00057 PrgDisj* d = static_cast<PrgDisj*>(head);
00058 support = PrgEdge::newEdge(h.node(), PrgEdge::CHOICE_EDGE, PrgEdge::DISJ_NODE);
00059 bool ok = true;
00060 for (PrgDisj::atom_iterator it = d->begin(), end = d->end(); it != end && ok; ++it) {
00061 assert(it->isChoice() && it->isAtom());
00062 PrgAtom* at = prg_->getAtom(it->node());
00063 if (!at->relevant()) { continue; }
00064 if (!at->inUpper()) { ok = addHeadToUpper(at, *it, support); }
00065 at->addSupport(support);
00066 }
00067 return ok;
00068 }
00070
00071
00072
00073
00075 bool Preprocessor::preprocessEq(uint32 maxIters) {
00076 uint32 startVar = prg_->ctx()->numVars() + 1;
00077 ValueRep res = value_true;
00078 pass_ = 0;
00079 maxPass_ = maxIters;
00080 HeadRange atoms = HeadRange(prg_->atom_begin() + prg_->startAtom(), prg_->atom_end());
00081 bodyInfo_.resize( prg_->numBodies() + 1 );
00082 do {
00083 if (++pass_ > 1) {
00084 for (HeadIter it = prg_->atom_begin(), end = atoms.second; it != end; ) {
00085 while (it != atoms.first){ (*it)->setInUpper(false); ++it; }
00086 while (it != end) { (*it)->clearLiteral(false); (*it)->setInUpper(false); ++it; }
00087 }
00088 for (HeadIter it = prg_->disj_begin(), end = prg_->disj_end(); it != end; ++it) {
00089 (*it)->clearLiteral(false);
00090 (*it)->setInUpper(false);
00091 }
00092 prg_->ctx()->resizeVars(startVar);
00093 litToNode_.clear();
00094 }
00095 VarVec& supported = prg_->getSupportedBodies(true);
00096 if (!classifyProgram(supported)) { return false; }
00097 res = simplifyClassifiedProgram(atoms, pass_ != maxPass_, supported);
00098 } while (res == value_free && pass_ != maxPass_);
00099 return res != value_false;
00100 }
00101
00102
00103
00104 bool Preprocessor::classifyProgram(const VarVec& supported) {
00105 Var bodyId; PrgBody* body;
00106 VarVec::size_type index = 0;
00107 follow_.clear();
00108 if (!prg_->propagate(true)) { return false; }
00109 for (VarVec::size_type i = 0;;) {
00110 while ( (bodyId = nextBodyId(index)) != varMax ) {
00111 body = addBodyVar(bodyId);
00112 if (prg_->hasConflict()) { return false; }
00113 if (!addHeadsToUpper(body)) { return false; }
00114 }
00115 follow_.clear();
00116 index = 0;
00117
00118 for (; i < supported.size(); ++i) {
00119 bodyId = supported[i];
00120 body = prg_->getBody(bodyId);
00121 if (bodyInfo_[bodyId].bSeen == 0 && body->relevant()) {
00122 follow_.push_back(bodyId);
00123 break;
00124 }
00125 else if (!body->relevant() && body->hasVar()) {
00126 body->clearLiteral(false);
00127 }
00128 }
00129 if (follow_.empty()) break;
00130 }
00131 return !prg_->hasConflict();
00132 }
00133
00134 ValueRep Preprocessor::simplifyClassifiedProgram(const HeadRange& atoms, bool more, VarVec& supported) {
00135 ValueRep res = value_true, simp;
00136 if (!prg_->propagate()) { return value_false; }
00137 supported.clear();
00138
00139 for (uint32 i = 0; i != prg_->numBodies(); ++i) {
00140 PrgBody* b = prg_->getBody(i);
00141 if (bodyInfo_[i].bSeen == 0 || !b->relevant()) {
00142
00143
00144
00145 b->clearLiteral(true);
00146 b->markRemoved();
00147 }
00148 else if ( (simp = simplifyBody(b, more, supported)) != value_true ) {
00149 if (simp == value_false) { return simp; }
00150 res = value_free;
00151 }
00152 }
00153 if (!prg_->propagate()) { return value_false; }
00154 for (LogicProgram::VarIter it = prg_->unfreeze_begin(), end = prg_->unfreeze_end(); it != end; ++it) {
00155 PrgAtom* a = prg_->getAtom(*it);
00156 ValueRep v = a->value();
00157 if (!a->simplifySupports(*prg_, true)){ return value_false; }
00158 else if (!a->inUpper() && v != value_false){
00159 if (!prg_->assignValue(a, value_false)) { return value_false; }
00160 if (more && a->hasDep(PrgAtom::dep_all)) { res = value_free; }
00161 }
00162 }
00163 if (!prg_->propagate()) { return value_false; }
00164 bool strong = more && res == value_true;
00165 HeadRange heads[2] = { HeadRange(prg_->disj_begin(), prg_->disj_end()), atoms };
00166 for (const HeadRange* range = heads, *endR = heads+2; range != endR; ++range) {
00167 for (HeadIter it = range->first, end = range->second; it != end; ++it) {
00168 PrgHead* head = *it;
00169 if ((simp = simplifyHead(head, strong)) != value_true) {
00170 if (simp == value_false){ return simp; }
00171 else if (strong) { strong = false; res = value_free; }
00172 }
00173 }
00174 }
00175 if (!prg_->propagate()) { res = value_false; }
00176 return res;
00177 }
00178
00179
00180 PrgBody* Preprocessor::addBodyVar(Var bodyId) {
00181
00182 PrgBody* body = prg_->getBody(bodyId);
00183 assert((body->isSupported() && !body->eq()) || body->hasVar());
00184 body->clearLiteral(false);
00185 bodyInfo_[bodyId].bSeen = 1;
00186 bool known = bodyInfo_[bodyId].known == body->size();
00187 uint32 eqId;
00188 if (!body->simplifyBody(*prg_, known, &eqId) || !body->simplifyHeads(*prg_, false)) {
00189 prg_->setConflict();
00190 return body;
00191 }
00192 if ((!body->hasHeads() && body->value() != value_false) || !body->relevant()) {
00193 body->markRemoved();
00194 return body;
00195 }
00196 if (eqId == bodyId) {
00197
00198 body->assignVar(*prg_);
00199 if (!known) { body->markDirty(); }
00200 else if (body->size() == 1) {
00201
00202
00203
00204 PrgAtom* a = prg_->getAtom(body->goal(0).var());
00205 PrgBody* r = 0;
00206 uint32 rId = varMax;
00207 assert(a->var() == body->var());
00208 if (body->goal(0).sign()) {
00209 Var dualAtom = getRootAtom(body->literal());
00210 a = dualAtom != varMax ? prg_->getAtom(dualAtom) : 0;
00211 }
00212 if (a && a->supps_begin()->isBody()) {
00213 rId = a->supps_begin()->node();
00214 r = prg_->getBody(rId);
00215 if (r && r->var() == a->var()) {
00216 mergeEqBodies(body, rId, false);
00217 }
00218 }
00219 }
00220 }
00221 else {
00222
00223 mergeEqBodies(body, eqId, true);
00224 }
00225 return body;
00226 }
00227
00228
00229
00230
00231
00232
00233 bool Preprocessor::addHeadsToUpper(PrgBody* body) {
00234 PrgHead* head;
00235 PrgEdge support;
00236 bool ok = !prg_->hasConflict();
00237 int dirty= 0;
00238 for (PrgBody::head_iterator it = body->heads_begin(), end = body->heads_end(); it != end && ok; ++it) {
00239 head = prg_->getHead(*it);
00240 support= PrgEdge::newEdge(body->id(), it->type(), PrgEdge::BODY_NODE);
00241 if (head->relevant() && head->value() != value_false) {
00242 if (body->value() == value_true && head->isAtom()) {
00243
00244
00245 head->setIgnoreScc(true);
00246 if (support.isNormal() && head->isAtom()) {
00247 ok = propagateAtomValue(static_cast<PrgAtom*>(head), value_true);
00248 }
00249 }
00250 if (!head->inUpper()) {
00251
00252 ok = addHeadToUpper(head, *it, support);
00253 }
00254 else if (head->supports() && head->supps_begin()->isNormal()) {
00255 PrgEdge source = *head->supps_begin();
00256 assert(source.isBody());
00257 if (prg_->getBody(source.node())->var() == body->var()) {
00258
00259 head->markDirty();
00260 }
00261 }
00262 head->addSupport(support, PrgHead::no_simplify);
00263 }
00264 dirty += (head->eq() || head->value() == value_false);
00265 }
00266 if (dirty) {
00267
00268 prg_->getBody(body->id())->markHeadsDirty();
00269 }
00270 return ok;
00271 }
00272
00273
00274
00275
00276
00277
00278
00279
00280 bool Preprocessor::propagateAtomVar(Var atomId, PrgAtom* a, PrgEdge source) {
00281 PrgAtom* comp = 0;
00282 bool fullEq = eq();
00283 bool removeAtom = a->value() == value_true || a->value() == value_false;
00284 bool removeNeg = removeAtom || a->value() == value_weak_true;
00285 Literal aLit = a->literal();
00286 if (fullEq) {
00287 if (getRootAtom(aLit) == varMax) {
00288 setRootAtom(aLit, atomId);
00289 }
00290 else if (prg_->mergeEqAtoms(a, getRootAtom(aLit))) {
00291 assert(source.isBody());
00292 removeAtom = true;
00293 removeNeg = true;
00294 PrgBody* B = prg_->getBody(source.node());
00295 a->setEqGoal(posLit(a->id()));
00296
00297 if (getRootAtom(~aLit) != varMax && B->literal() == aLit && B->size() == 1 && B->goal(0).sign()) {
00298 a->setEqGoal(B->goal(0));
00299 }
00300 a->clearLiteral(true);
00301 }
00302 else { return false; }
00303 }
00304 if (getRootAtom(~aLit) != varMax) {
00305 PrgAtom* negA = prg_->getAtom(getRootAtom(~aLit));
00306 assert(aLit == ~negA->literal());
00307
00308 ValueRep cv = value_free;
00309 uint32 mark = 0;
00310 if (a->value() != value_free && (cv = (value_false | (a->value()^value_true))) != negA->value()) {
00311 mark = 1;
00312 if (!propagateAtomValue(negA, cv)) {
00313 return false;
00314 }
00315 }
00316 if ( !removeAtom ) {
00317 for (PrgAtom::dep_iterator it = (comp=negA)->deps_begin(); it != comp->deps_end(); ++it) {
00318 bodyInfo_[it->var()].mBody = 1;
00319 if (mark) { prg_->getBody(it->var())->markDirty(); }
00320 }
00321 }
00322 }
00323 for (PrgAtom::dep_iterator it = a->deps_begin(), end = a->deps_end(); it != end; ++it) {
00324 Var bodyId = it->var();
00325 PrgBody* bn = prg_->getBody(bodyId);
00326 if (bn->relevant()) {
00327 bool wasSup = bn->isSupported();
00328 bool isSup = wasSup || (a->value() != value_false && !it->sign() && bn->propagateSupported(atomId));
00329 bool seen = false;
00330 bool dirty = removeAtom || (removeNeg && it->sign());
00331 if (fullEq) {
00332 seen = bodyInfo_[bodyId].bSeen != 0;
00333 dirty |= bodyInfo_[bodyId].mBody == 1;
00334 if (++bodyInfo_[bodyId].known == bn->size() && !seen && isSup) {
00335 follow_.push_back( bodyId );
00336 seen = true;
00337 }
00338 }
00339 if (!seen && isSup && !wasSup) {
00340 prg_->getSupportedBodies(false).push_back(bodyId);
00341 }
00342 if (dirty) {
00343 bn->markDirty();
00344 if (a->eq()) {
00345 bn->markHeadsDirty();
00346 }
00347 }
00348 }
00349 }
00350 if (removeAtom) { a->clearDeps(PrgAtom::dep_all); }
00351 else if (removeNeg) { a->clearDeps(PrgAtom::dep_neg); }
00352 if (comp) {
00353 for (PrgAtom::dep_iterator it = comp->deps_begin(), end = comp->deps_end(); it != end; ++it) {
00354 bodyInfo_[it->var()].mBody = 0;
00355 }
00356 }
00357 return true;
00358 }
00359
00360
00361 bool Preprocessor::propagateAtomValue(PrgAtom* atom, ValueRep val) {
00362
00363 return prg_->assignValue(atom, val) && prg_->propagate(false);
00364 }
00365
00366 bool Preprocessor::mergeEqBodies(PrgBody* body, Var rootId, bool equalLits) {
00367 PrgBody* root = prg_->mergeEqBodies(body, rootId, equalLits, false);
00368 if (root && root != body && bodyInfo_[root->id()].bSeen == 0) {
00369
00370
00371
00372 body->clearHeads();
00373 body->markRemoved();
00374 }
00375 return root != 0;
00376 }
00377
00378 bool Preprocessor::hasRootLiteral(PrgBody* body) const {
00379 return body->size() >= 1
00380 && getRootAtom(body->literal()) == varMax
00381 && getRootAtom(~body->literal())== varMax;
00382 }
00383
00384
00385
00386
00387
00388
00389 ValueRep Preprocessor::simplifyBody(PrgBody* b, bool reclass, VarVec& supported) {
00390 assert(b->relevant() && bodyInfo_[b->id()].bSeen == 1);
00391 bodyInfo_[b->id()].bSeen = 0;
00392 bodyInfo_[b->id()].known = 0;
00393 bool hadHeads = b->hasHeads();
00394 uint32 eqId = b->id();
00395 if (!b->simplify(*prg_, true, &eqId)) {
00396 return value_false;
00397 }
00398 ValueRep ret = value_true;
00399 if (reclass) {
00400 if (hadHeads && b->value() == value_false) {
00401 assert(b->hasHeads() == false);
00402
00403
00404 if (!b->relevant()) {
00405 b->clearLiteral(true);
00406 }
00407 }
00408 else if (!b->hasHeads() && b->value() != value_false && b->var() != 0) {
00409
00410
00411
00412 if (getRootAtom(b->literal()) == varMax) { ret = value_weak_true; }
00413 b->clearLiteral(true);
00414 b->markRemoved();
00415 }
00416 else if (b->value() == value_true && b->var() != 0) {
00417
00418 for (PrgBody::head_iterator it = b->heads_begin(), end = b->heads_end(); it != end; ++it) {
00419 if (it->isNormal() && prg_->getHead(*it)->var() != 0) {
00420 ret = value_weak_true;
00421 break;
00422 }
00423 }
00424 b->markDirty();
00425 }
00426 }
00427 if (b->relevant() && eqId != b->id() && (reclass || prg_->getBody(eqId)->var() == b->var())) {
00428
00429 Var bVar = b->var();
00430 bool rootVar = hasRootLiteral(b);
00431 PrgBody* eqBody = prg_->mergeEqBodies(b, eqId, true, true);
00432 if (eqBody && rootVar && bVar != eqBody->var()) {
00433 ret = value_weak_true;
00434 }
00435 }
00436 if (b->relevant() && b->resetSupported()) {
00437 supported.push_back(b->id());
00438 }
00439 return ret;
00440 }
00441
00442
00443
00444
00445
00446
00447
00448
00449 ValueRep Preprocessor::simplifyHead(PrgHead* h, bool more) {
00450 if (!h->hasVar() || !h->relevant()) {
00451
00452 h->clearLiteral(false);
00453 h->markRemoved();
00454 h->clearSupports();
00455 h->setInUpper(false);
00456 return value_true;
00457 }
00458 assert(h->inUpper());
00459 ValueRep v = h->value();
00460 ValueRep ret = value_true;
00461 PrgEdge support = h->supports() ? *h->supps_begin() : PrgEdge::noEdge();
00462 uint32 numSuppLits= 0;
00463 if (!h->simplifySupports(*prg_, true, &numSuppLits)) {
00464 return value_false;
00465 }
00466 if (v != h->value() && (h->value() == value_false || (h->value() == value_true && h->var() != 0))) {
00467 ret = value_weak_true;
00468 }
00469 if (more) {
00470 if (numSuppLits == 0 && h->hasVar()) {
00471
00472 ret = value_weak_true;
00473 }
00474 else if (h->supports() > 0 && h->supps_begin()->rep != support.rep) {
00475
00476 ret = value_weak_true;
00477 }
00478 else if ((support.isNormal() && h->supports() == 1) || (h->supports() > 1 && numSuppLits == 1 && h->isAtom())) {
00479 assert(support.isBody());
00480 PrgBody* supBody = prg_->getBody(support.node());
00481 if (supBody->literal() != h->literal()) {
00482 if (h->supports() > 1) {
00483
00484 EdgeVec temp(h->supps_begin(), h->supps_end());
00485 h->clearSupports();
00486 support = temp[0];
00487 for (EdgeIterator it = temp.begin(), end = temp.end(); it != end; ++it) {
00488 assert(!it->isDisj());
00489 PrgBody* B = prg_->getBody(it->node());
00490 if (it->isNormal() && B->size() == 1 && B->goal(0).sign()) {
00491 support = *it;
00492 }
00493 B->removeHead(h, it->type());
00494 }
00495 supBody = prg_->getBody(support.node());
00496 supBody->addHead(h, support.type());
00497 if (!supBody->simplifyHeads(*prg_, true)) {
00498 return value_false;
00499 }
00500 }
00501 ret = value_weak_true;
00502 if (h->value() == value_weak_true || h->value() == value_true) {
00503 supBody->assignValue(h->value());
00504 supBody->propagateValue(*prg_, true);
00505 }
00506 }
00507 }
00508 }
00509 return ret;
00510 }
00511
00512 } }