dlvhex
2.5.0
|
00001 /* dlvhex -- Answer-Set Programming with external interfaces. 00002 * Copyright (C) 2005-2007 Roman Schindlauer 00003 * Copyright (C) 2006-2015 Thomas Krennwallner 00004 * Copyright (C) 2009-2016 Peter Schüller 00005 * Copyright (C) 2011-2016 Christoph Redl 00006 * Copyright (C) 2015-2016 Tobias Kaminski 00007 * Copyright (C) 2015-2016 Antonius Weinzierl 00008 * 00009 * This file is part of dlvhex. 00010 * 00011 * dlvhex is free software; you can redistribute it and/or modify it 00012 * under the terms of the GNU Lesser General Public License as 00013 * published by the Free Software Foundation; either version 2.1 of 00014 * the License, or (at your option) any later version. 00015 * 00016 * dlvhex is distributed in the hope that it will be useful, but 00017 * WITHOUT ANY WARRANTY; without even the implied warranty of 00018 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 00019 * Lesser General Public License for more details. 00020 * 00021 * You should have received a copy of the GNU Lesser General Public 00022 * License along with dlvhex; if not, write to the Free Software 00023 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 00024 * 02110-1301 USA. 00025 */ 00026 00034 #include "dlvhex2/Nogood.h" 00035 00036 #include <iostream> 00037 #include <sstream> 00038 #include <algorithm> 00039 #include "dlvhex2/Logger.h" 00040 #include "dlvhex2/Printer.h" 00041 #include <boost/functional/hash.hpp> 00042 00043 DLVHEX_NAMESPACE_BEGIN 00044 00045 // ---------- Class Nogood ---------- 00046 00047 //#define DBGLOGD(X,Y) DBGLOG(X,Y) 00048 #define DBGLOGD(X,Y) do{}while(false); 00049 00050 namespace 00051 { 00052 struct VariableSorter 00053 { 00054 typedef std::pair<ID, std::vector<int> > VarType; 00055 bool operator() (VarType p1, VarType p2) { 00056 for (uint32_t i = 0; i < p1.second.size(); i++) { 00057 if (p1.second[i] < p2.second[i]) return true; 00058 if (p1.second[i] > p2.second[i]) return false; 00059 } 00060 if (p2.second.size() > p1.second.size()) return true; 00061 00062 // they are considered equal 00063 return false; 00064 } 00065 }; 00066 } 00067 00068 00069 Nogood::Nogood() : ground(true) 00070 { 00071 } 00072 00073 Nogood::Nogood(InterpretationConstPtr assigned, InterpretationConstPtr interpretation) 00074 : ground(true) 00075 { 00076 bm::bvector<>::enumerator en = assigned->getStorage().first(); 00077 bm::bvector<>::enumerator en_end = assigned->getStorage().end(); 00078 while (en < en_end) { 00079 insert(NogoodContainer::createLiteral(*en, interpretation->getFact(*en))); 00080 en++; 00081 } 00082 } 00083 00084 void Nogood::recomputeHash() 00085 { 00086 hashValue = 0; 00087 BOOST_FOREACH (ID lit, *this) { 00088 boost::hash_combine(hashValue, lit.kind); 00089 boost::hash_combine(hashValue, lit.address); 00090 } 00091 } 00092 00093 00094 size_t Nogood::getHash() 00095 { 00096 return hashValue; 00097 } 00098 00099 00100 const Nogood& Nogood::operator=(const Nogood& other) 00101 { 00102 this->Set<ID>::operator=(other); 00103 hashValue = other.hashValue; 00104 ground = other.ground; 00105 return *this; 00106 } 00107 00108 00109 bool Nogood::operator==(const Nogood& ng2) const 00110 { 00111 00112 // compare hash value 00113 if (hashValue != ng2.hashValue) return false; 00114 00115 // compare content 00116 if (size() != ng2.size()) return false; 00117 00118 const_set_iterator<ID> it1 = ((const Nogood*)this)->begin(); 00119 const_set_iterator<ID> it2 = ng2.begin(); 00120 while(it1 != end()) { 00121 if (*it1 != *it2) return false; 00122 ++it1; 00123 ++it2; 00124 } 00125 00126 return true; 00127 } 00128 00129 00130 bool Nogood::operator!=(const Nogood& ng2) const 00131 { 00132 return !(this->operator==(ng2)); 00133 } 00134 00135 00136 std::ostream& Nogood::print(std::ostream& o) const 00137 { 00138 o << "{ "; 00139 bool first = true; 00140 BOOST_FOREACH (ID lit, *this) { 00141 if (!first) { 00142 o << ", "; 00143 } 00144 first = false; 00145 o << (lit.isNaf() ? std::string("-") : std::string("")) << lit.address; 00146 } 00147 o << " }"; 00148 return o; 00149 } 00150 00151 00152 std::string Nogood::getStringRepresentation(RegistryPtr reg) const 00153 { 00154 00155 std::stringstream ss; 00156 RawPrinter printer(ss, reg); 00157 ss << "{ "; 00158 bool first = true; 00159 BOOST_FOREACH (ID lit, *this) { 00160 if (!first) { 00161 ss << ", "; 00162 } 00163 first = false; 00164 ss << (lit.isNaf() ? "-" : ""); 00165 if (lit.isOrdinaryGroundAtom()) { 00166 printer.print(reg->ogatoms.getIDByAddress(lit.address)); 00167 } 00168 else { 00169 printer.print(reg->onatoms.getIDByAddress(lit.address)); 00170 } 00171 } 00172 ss << " }"; 00173 return ss.str(); 00174 } 00175 00176 00177 Nogood Nogood::resolve(const Nogood& ng2, IDAddress groundlitadr) 00178 { 00179 // resolvent = union of this and ng2 minus both polarities of the resolved literal 00180 Nogood resolvent = *this; 00181 resolvent.insert(ng2.begin(), ng2.end()); 00182 resolvent.erase(NogoodContainer::createLiteral(groundlitadr, true)); 00183 resolvent.erase(NogoodContainer::createLiteral(groundlitadr, false)); 00184 DBGLOG(DBG, "Resolution " << *this << " with " << ng2 << ": " << resolvent); 00185 assert(resolvent.size() < this->size() + ng2.size() && "resolvent is not smaller than the union of the two nogoods; ensure that the resolved literal is chosen correctly"); 00186 return resolvent; 00187 } 00188 00189 00190 Nogood Nogood::resolve(const Nogood& ng2, ID lit) 00191 { 00192 // resolvent = union of this and ng2 minus both polarities of the resolved literal 00193 Nogood resolvent = *this; 00194 resolvent.insert(ng2.begin(), ng2.end()); 00195 resolvent.erase(NogoodContainer::createLiteral(lit.address, true, lit.isOrdinaryGroundAtom())); 00196 resolvent.erase(NogoodContainer::createLiteral(lit.address, false, lit.isOrdinaryGroundAtom())); 00197 DBGLOG(DBG, "Resolution " << *this << " with " << ng2 << ": " << resolvent); 00198 assert(resolvent.size() < this->size() + ng2.size() && "resolvent is not smaller than the union of the two nogoods; ensure that the resolved literal is chosen correctly"); 00199 return resolvent; 00200 } 00201 00202 00203 void Nogood::applyVariableSubstitution(RegistryPtr reg, const std::map<ID, ID>& subst) 00204 { 00205 00206 DBGLOG(DBG, "Applying variable substitution to " << getStringRepresentation(reg)); 00207 Nogood newng; 00208 BOOST_FOREACH (ID lit, *this) { 00209 OrdinaryAtom oatom = reg->lookupOrdinaryAtom(lit); 00210 bool changed = false; 00211 for (uint32_t t = 1; t < oatom.tuple.size(); t++) { 00212 if (subst.count(oatom.tuple[t]) > 0) { 00213 oatom.tuple[t] = subst.at(oatom.tuple[t]); 00214 changed = true; 00215 } 00216 } 00217 ID newlit = lit; 00218 if (changed) newlit.address = reg->storeOrdinaryAtom(oatom).address; 00219 newng.insert(NogoodContainer::createLiteral(newlit)); 00220 } 00221 DBGLOG(DBG, "New nogood is " << newng.getStringRepresentation(reg)); 00222 *this = newng; 00223 } 00224 00225 00226 void Nogood::heuristicNormalization(RegistryPtr reg) 00227 { 00228 00229 // This method renames the variables in a nonground nogood 00230 // such that multiple nogoods which differ only in the variable naming 00231 // are likely to become equivalent. 00232 // This is useful for reducing redundancy in resolution. 00233 00234 // For this we sort the variables such that for variables X, Y 00235 // we have X < Y 00236 // iff Y occurs more often than X 00237 // or Y occurs as often as X but more often at first argument position 00238 // or Y occurs as often as X also at first argument position but more often at the second, 00239 // etc. 00240 // and X = Y otherwise. 00241 00242 if (isGround()) return; 00243 DBGLOG(DBG, "Normalizing " << getStringRepresentation(reg)); 00244 00245 // prepare statistics 00246 std::map<ID, std::vector<int> > vars; 00247 BOOST_FOREACH (ID id, *this) { 00248 const OrdinaryAtom& oatom = reg->lookupOrdinaryAtom(id); 00249 for (uint32_t i = 1; i < oatom.tuple.size(); ++i) { 00250 if (oatom.tuple[i].isVariableTerm()) { 00251 std::vector<int>& pos = vars[oatom.tuple[i]]; 00252 while (pos.size() < i + 1) pos.push_back(0); 00253 pos[0]++; 00254 pos[i]++; 00255 } 00256 } 00257 } 00258 std::vector<VariableSorter::VarType> sortedVars; 00259 BOOST_FOREACH (VariableSorter::VarType v, vars) { 00260 sortedVars.push_back(v); 00261 } 00262 00263 // sort 00264 VariableSorter sorter; 00265 std::sort(sortedVars.begin(), sortedVars.end(), sorter); 00266 00267 // assign new variable names 00268 std::map<ID, ID> renaming; 00269 int i = 0; 00270 BOOST_FOREACH (VariableSorter::VarType v, sortedVars) { 00271 std::stringstream ss; 00272 ss << "X" << i++; 00273 renaming[v.first] = reg->storeVariableTerm(ss.str()); 00274 } 00275 applyVariableSubstitution(reg, renaming); 00276 DBGLOG(DBG, "Normalized " << getStringRepresentation(reg)); 00277 } 00278 00279 00280 void Nogood::insert(ID lit) 00281 { 00282 // strip off property flags 00283 lit = NogoodContainer::createLiteral(lit); 00284 00285 // actual insertion 00286 Set<ID>::insert(lit); 00287 ground &= lit.isOrdinaryGroundAtom(); 00288 } 00289 00290 00291 bool Nogood::isGround() const 00292 { 00293 return ground; 00294 } 00295 00296 00297 bool Nogood::match(RegistryPtr reg, ID atomID, Nogood& instance) const 00298 { 00299 00300 DBGLOG(DBG, "Matching " << *this << " with " << atomID); 00301 00302 const OrdinaryAtom& atom = reg->ogatoms.getByID(atomID); 00303 00304 // find an element in the nogood with unifies with atom 00305 BOOST_FOREACH (ID natID, *this) { 00306 const OrdinaryAtom& nat = natID.isOrdinaryGroundAtom() ? reg->ogatoms.getByID(natID) : reg->onatoms.getByID(natID); 00307 00308 if (atom.unifiesWith(nat, reg)) { 00309 DBGLOG(DBG, "Unifies with " << natID); 00310 00311 // compute unifier 00312 std::map<ID, ID> unifier; 00313 int i = 0; 00314 BOOST_FOREACH (ID t, nat.tuple) { 00315 if (t.isVariableTerm()) { 00316 unifier[t] = atom.tuple[i]; 00317 DBGLOG(DBG, "Unifier: " << t << " --> " << atom.tuple[i]); 00318 } 00319 i++; 00320 } 00321 00322 // apply unifier to the overall nogood 00323 DBGLOG(DBG, "Applying unifier"); 00324 BOOST_FOREACH (ID natID2, *this) { 00325 if (natID2.isOrdinaryGroundAtom()) { 00326 instance.insert(natID2); 00327 } 00328 else { 00329 OrdinaryAtom nat2 = reg->onatoms.getByID(natID2); 00330 bool ground = true; 00331 for (uint32_t i = 0; i < nat2.tuple.size(); ++i) { 00332 if (unifier.find(nat2.tuple[i]) != unifier.end()) { 00333 DBGLOG(DBG, "Substituting " << nat2.tuple[i] << " by " << unifier[nat2.tuple[i]]); 00334 nat2.tuple[i] = unifier[nat2.tuple[i]]; 00335 } 00336 if (nat2.tuple[i].isVariableTerm()) ground = false; 00337 } 00338 if (ground) { 00339 nat2.kind &= (ID::ALL_ONES ^ ID::SUBKIND_MASK); 00340 nat2.kind |= ID::SUBKIND_ATOM_ORDINARYG; 00341 } 00342 instance.insert(NogoodContainer::createLiteral(reg->storeOrdinaryAtom(nat2).address, !natID2.isNaf(), ground)); 00343 } 00344 } 00345 DBGLOG(DBG, "Instance: " << instance); 00346 if (!instance.isGround()) DBGLOG(DBG, "Note: Instance is not ground!"); 00347 return true; 00348 } 00349 } 00350 // no match 00351 return false; 00352 } 00353 00354 00355 #ifndef NDEBUG 00356 00357 std::string Nogood::dbgsave() const 00358 { 00359 std::stringstream ss; 00360 BOOST_FOREACH (ID id, *this) { 00361 ss << (id.isNaf() ? "-" : "+") << "/" << id.address << ";"; 00362 } 00363 return ss.str(); 00364 } 00365 00366 00367 void Nogood::dbgload(std::string str) 00368 { 00369 00370 while (str.find_first_of("/") != std::string::npos) { 00371 std::string sign = str.substr(0, str.find_first_of("/")); 00372 std::string adr = str.substr(str.find_first_of("/") + 1, str.find_first_of(";")); 00373 str = str.substr(str.find_first_of(";") + 1); 00374 insert(NogoodContainer::createLiteral(atoi(str.c_str()), sign[0] == '+')); 00375 } 00376 } 00377 #endif 00378 00379 // ---------- Class NogoodSet ---------- 00380 00381 const NogoodSet& NogoodSet::operator=(const NogoodSet& other) 00382 { 00383 nogoods = other.nogoods; 00384 freeIndices = other.freeIndices; 00385 nogoodsWithHash = other.nogoodsWithHash; 00386 00387 return *this; 00388 } 00389 00390 00391 // reorders the nogoods such that there are no free indices in the range 0-(getNogoodCount()-1) 00392 void NogoodSet::defragment() 00393 { 00394 if (freeIndices.size() == 0) return; 00395 00396 int free = 0; 00397 int used = nogoods.size() - 1; 00398 while (free < used) { 00399 // let used point to the last element which is not free 00400 while (used > 0 && freeIndices.count(used) > 0) { 00401 nogoods.pop_back(); 00402 used--; 00403 } 00404 // let free point to the next free index in the range 0-(ngg.nogoods.size()-1) 00405 while (free < (int)nogoods.size() - 1 && freeIndices.count(free) == 0) free++; 00406 // move used to free 00407 if (free < used) { 00408 nogoods[free] = nogoods[used]; 00409 addCount[free] = addCount[used]; 00410 nogoods.pop_back(); 00411 addCount.pop_back(); 00412 nogoodsWithHash[nogoods[free].getHash()].erase(used); 00413 nogoodsWithHash[nogoods[free].getHash()].insert(free); 00414 freeIndices.erase(free); 00415 free++; 00416 used--; 00417 } 00418 } 00419 #ifndef NDEBUG 00420 // there must not be pointers to non-existing nogoods 00421 { 00422 typedef std::pair<size_t, Set<int> > Pair; 00423 BOOST_FOREACH (Pair p, nogoodsWithHash) { 00424 BOOST_FOREACH (int i, p.second) { 00425 assert (i < (int)nogoods.size()); 00426 } 00427 } 00428 } 00429 #endif 00430 freeIndices.clear(); 00431 } 00432 00433 00434 int NogoodSet::addNogood(Nogood ng) 00435 { 00436 00437 ng.recomputeHash(); 00438 DBGLOG(DBG, "Hash of " << ng << " is " << ng.getHash()); 00439 00440 // check if ng is already present 00441 BOOST_FOREACH (int i, nogoodsWithHash[ng.getHash()]) { 00442 if (nogoods[i] == ng) { 00443 addCount[i]++; 00444 DBGLOG(DBG, "Already contained with index " << i); 00445 return i; 00446 } 00447 } 00448 00449 // nogood is not present 00450 int index; 00451 if (freeIndices.size() == 0) { 00452 nogoods.push_back(ng); 00453 addCount.push_back(1); 00454 index = nogoods.size() - 1; 00455 } 00456 else { 00457 index = *freeIndices.begin(); 00458 nogoods[index] = ng; 00459 addCount[index] = 1; 00460 freeIndices.erase(index); 00461 } 00462 DBGLOG(DBG, "Adding with index " << index); 00463 00464 nogoodsWithHash[ng.getHash()].insert(index); 00465 return index; 00466 } 00467 00468 00469 Nogood& NogoodSet::getNogood(int index) 00470 { 00471 return nogoods[index]; 00472 } 00473 00474 00475 const Nogood& NogoodSet::getNogood(int index) const 00476 { 00477 return nogoods[index]; 00478 } 00479 00480 00481 void NogoodSet::removeNogood(int nogoodIndex) 00482 { 00483 addCount[nogoodIndex] = 0; 00484 nogoodsWithHash[nogoods[nogoodIndex].getHash()].erase(nogoodIndex); 00485 freeIndices.insert(nogoodIndex); 00486 // defragment(); // make sure that the nogood vector does not contain free slots 00487 } 00488 00489 00490 void NogoodSet::removeNogood(Nogood ng) 00491 { 00492 ng.recomputeHash(); 00493 00494 // check if ng is present 00495 BOOST_FOREACH (int i, nogoodsWithHash[ng.getHash()]) { 00496 if (nogoods[i] == ng) { 00497 DBGLOG(DBG, "Deleting nogood " << ng << " (index: " << i << ")"); 00498 // yes: delete it 00499 removeNogood(i); 00500 return; 00501 } 00502 } 00503 return; 00504 } 00505 00506 00507 int NogoodSet::getNogoodCount() const 00508 { 00509 return nogoods.size() - freeIndices.size(); 00510 } 00511 00512 00513 void NogoodSet::forgetLeastFrequentlyAdded() 00514 { 00515 00516 int mac = 0; 00517 for (uint32_t i = 0; i < nogoods.size(); i++) { 00518 mac = mac > addCount[i] ? mac : addCount[i]; 00519 } 00520 // delete those with an add count of less than 5% of the maximum add count 00521 for (uint32_t i = 0; i < nogoods.size(); i++) { 00522 if (addCount[i] < mac * 0.05) { 00523 DBGLOG(DBG, "Forgetting nogood " << nogoods[i]); 00524 removeNogood(i); 00525 } 00526 } 00527 } 00528 00529 00530 std::string NogoodSet::getStringRepresentation(RegistryPtr reg) const 00531 { 00532 00533 std::stringstream ss; 00534 bool first = true; 00535 BOOST_FOREACH (Nogood ng, nogoods) { 00536 if (!first) { 00537 ss << ", "; 00538 } 00539 first = false; 00540 ss << ng.getStringRepresentation(reg); 00541 } 00542 return ss.str(); 00543 } 00544 00545 00546 std::ostream& NogoodSet::print(std::ostream& o) const 00547 { 00548 o << "{ "; 00549 for (std::vector<Nogood>::const_iterator it = nogoods.begin(); it != nogoods.end(); ++it) { 00550 if (it != nogoods.begin()) o << ", "; 00551 o << (*it); 00552 } 00553 o << " }"; 00554 return o; 00555 } 00556 00557 00558 void SimpleNogoodContainer::addNogood(Nogood ng) 00559 { 00560 boost::mutex::scoped_lock lock(mutex); 00561 ngg.addNogood(ng); 00562 } 00563 00564 00565 void SimpleNogoodContainer::removeNogood(Nogood ng) 00566 { 00567 boost::mutex::scoped_lock lock(mutex); 00568 ngg.removeNogood(ng); 00569 } 00570 00571 00572 Nogood& SimpleNogoodContainer::getNogood(int index) 00573 { 00574 boost::mutex::scoped_lock lock(mutex); 00575 return ngg.getNogood(index); 00576 } 00577 00578 00579 int SimpleNogoodContainer::getNogoodCount() 00580 { 00581 boost::mutex::scoped_lock lock(mutex); 00582 return ngg.getNogoodCount(); 00583 } 00584 00585 00586 void SimpleNogoodContainer::clear() 00587 { 00588 boost::mutex::scoped_lock lock(mutex); 00589 ngg = NogoodSet(); 00590 } 00591 00592 00593 void SimpleNogoodContainer::addAllResolvents(RegistryPtr reg, int maxSize) 00594 { 00595 00596 std::vector<Nogood> nogoodList; 00597 for (int i = 0; i < getNogoodCount(); i++) { 00598 nogoodList.push_back(getNogood(i)); 00599 nogoodList[nogoodList.size() - 1].heuristicNormalization(reg); 00600 } 00601 00602 // for all nogoods 00603 std::vector<Nogood> addList; 00604 int ng1i = 0; 00605 while (ng1i < (int)nogoodList.size()) { 00606 Nogood ng1 = nogoodList[ng1i]; 00607 DBGLOG(DBG, "Trying to resolve " << ng1.getStringRepresentation(reg)); 00608 00609 // rename all variables in ng1 to avoid name clashes 00610 DBGLOG(DBG, "Renaming all variables"); 00611 std::set<ID> vars; 00612 std::map<ID, ID> renaming; 00613 BOOST_FOREACH (ID id1, ng1) reg->getVariablesInID(id1, vars); 00614 BOOST_FOREACH (ID v, vars) { 00615 assert(!v.isAnonymousVariable() && "do not support anonymous variables in nogoods"); 00616 // just mark the variables as anonymous to ensure that they have a different ID 00617 renaming[v] = ID(v.kind | ID::PROPERTY_VAR_ANONYMOUS, v.address); 00618 } 00619 ng1.applyVariableSubstitution(reg, renaming); 00620 00621 // for all other nogoods 00622 for (uint32_t ng2i = 0; ng2i < nogoodList.size(); ng2i++) { 00623 const Nogood& ng2 = nogoodList[ng2i]; 00624 00625 // check if they unify 00626 DBGLOG(DBG, "Checking if " << ng1.getStringRepresentation(reg) << " unifies with " << ng2.getStringRepresentation(reg)); 00627 BOOST_FOREACH (ID id1, ng1) { 00628 BOOST_FOREACH (ID id2, ng2) { 00629 if (id1.isNaf() != id2.isNaf() && reg->lookupOrdinaryAtom(id1).unifiesWith(reg->lookupOrdinaryAtom(id2))) { 00630 // match id1 with id2 00631 std::map<ID, ID> match; 00632 const OrdinaryAtom& at1 = reg->lookupOrdinaryAtom(id1); 00633 const OrdinaryAtom& at2 = reg->lookupOrdinaryAtom(id2); 00634 for (uint32_t i = 1; i < at1.tuple.size(); i++) match[at1.tuple[i]] = at2.tuple[i]; 00635 Nogood ng1matched = ng1; 00636 ng1matched.applyVariableSubstitution(reg, match); 00637 00638 DBGLOG(DBG, "Resolving " << ng1matched.getStringRepresentation(reg) << "(" << ng1matched << ") with " << ng2.getStringRepresentation(reg) << " (" << ng2 << ")" << " on " << id2); 00639 Nogood resolvent = ng1matched.resolve(ng2, id2); 00640 // now assign new variable names to the renamed variables (names which occur neither in ng1 nor in ng2) 00641 std::set<ID> vars; 00642 std::map<ID, ID> backrenaming; 00643 BOOST_FOREACH (ID id1, ng1matched) reg->getVariablesInID(id1, vars); 00644 BOOST_FOREACH (ID id1, ng2) reg->getVariablesInID(id1, vars); 00645 typedef std::pair<ID, ID> KVPair; 00646 BOOST_FOREACH (KVPair kv, renaming) { 00647 ID newVar = ID_FAIL; 00648 int cnt = 0; 00649 while (newVar == ID_FAIL || vars.count(newVar) > 0) { 00650 std::stringstream ss; 00651 ss << reg->terms.getByID(kv.first).getUnquotedString(); 00652 if (cnt++ > 0) ss << cnt; 00653 newVar = reg->storeVariableTerm(ss.str()); 00654 } 00655 backrenaming[renaming[kv.first]] = newVar; 00656 } 00657 resolvent.applyVariableSubstitution(reg, backrenaming); 00658 resolvent.heuristicNormalization(reg); 00659 #ifdef DEBUG 00660 std::stringstream ss; 00661 RawPrinter printer(ss, reg); 00662 printer.print(id1); 00663 DBGLOG(DBG, "Computed resolvent " << resolvent.getStringRepresentation(reg) << " by resolving " << ss.str()); 00664 #endif 00665 // finally add the resolvent if its size is within the limit 00666 if (maxSize == -1 || resolvent.size() <= maxSize) { 00667 DBGLOG(DBG, "Adding the resolvent"); 00668 addNogood(resolvent); 00669 // if the nogood is not already present, then we also need to resolve it 00670 if (getNogoodCount() > (int)(nogoodList.size() + addList.size())) { 00671 DBGLOG(DBG, "Adding the resolvent " << resolvent.getStringRepresentation(reg) << " for further resolution because there were " << (getNogoodCount() - (nogoodList.size() + addList.size())) << " new nogoods"); 00672 addList.push_back(resolvent); 00673 } 00674 } 00675 } 00676 } 00677 } 00678 DBGLOG(DBG, "Finished checking " << ng2.getStringRepresentation(reg)); 00679 } 00680 00681 DBGLOG(DBG, "Finished checking " << ng1.getStringRepresentation(reg)); 00682 nogoodList.insert(nogoodList.end(), addList.begin(), addList.end()); 00683 addList.clear(); 00684 ng1i++; 00685 } 00686 } 00687 00688 00689 void SimpleNogoodContainer::forgetLeastFrequentlyAdded() 00690 { 00691 boost::mutex::scoped_lock lock(mutex); 00692 DBGLOG(DBG, "Nogood count before forgetting " << ngg.getNogoodCount()); 00693 ngg.forgetLeastFrequentlyAdded(); 00694 ngg.defragment(); 00695 DBGLOG(DBG, "Nogood count after forgetting " << ngg.getNogoodCount()); 00696 } 00697 00698 00699 void SimpleNogoodContainer::defragment() 00700 { 00701 ngg.defragment(); 00702 } 00703 00704 00705 DLVHEX_NAMESPACE_END 00706 00707 // vim:expandtab:ts=4:sw=4: 00708 // mode: C++ 00709 // End: