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 #define DLVHEX_BENCHMARK 00035 00036 #include "dlvhex2/NogoodGrounder.h" 00037 #include "dlvhex2/Logger.h" 00038 #include "dlvhex2/Registry.h" 00039 #include "dlvhex2/Printer.h" 00040 #include "dlvhex2/Benchmarking.h" 00041 #include "dlvhex2/Nogood.h" 00042 00043 #include <bm/bmalgo.h> 00044 00045 #include <boost/foreach.hpp> 00046 00047 DLVHEX_NAMESPACE_BEGIN 00048 00049 NogoodGrounder::NogoodGrounder(RegistryPtr reg, SimpleNogoodContainerPtr watched, SimpleNogoodContainerPtr destination, AnnotatedGroundProgram& agp) : 00050 reg(reg), watched(watched), destination(destination), agp(agp) 00051 { 00052 } 00053 00054 00055 void NogoodGrounder::resetWatched(SimpleNogoodContainerPtr watched) 00056 { 00057 this->watched = watched; 00058 } 00059 00060 00061 ImmediateNogoodGrounder::ImmediateNogoodGrounder(RegistryPtr reg, SimpleNogoodContainerPtr watched, SimpleNogoodContainerPtr destination, AnnotatedGroundProgram& agp) : 00062 NogoodGrounder(reg, watched, destination, agp), instantiatedNongroundNogoodsIndex(0) 00063 { 00064 } 00065 00066 00067 void ImmediateNogoodGrounder::update(InterpretationConstPtr partialInterpretation, InterpretationConstPtr factWasSet, InterpretationConstPtr changed) 00068 { 00069 00070 // go through all nonground nogoods which have not been instantiated so far 00071 int max = watched->getNogoodCount(); 00072 if (instantiatedNongroundNogoodsIndex >= max) instantiatedNongroundNogoodsIndex = 0; 00073 DBGLOG(DBG, "Updating nogood grounder from " << instantiatedNongroundNogoodsIndex << " to " << max); 00074 for (int i = instantiatedNongroundNogoodsIndex; i < max; ++i) { 00075 Nogood ng = watched->getNogood(i); 00076 DBGLOG(DBG, "Checking nogood " << ng.getStringRepresentation(reg)); 00077 if (ng.isGround()) continue; 00078 00079 DBGLOG(DBG, "Searching for watched literal in nogood " << i); 00080 int maxBoundVariables = 0; 00081 ID watchedLit = ID_FAIL; 00082 BOOST_FOREACH (ID lit, ng) { 00083 if (lit.isOrdinaryGroundAtom()) continue; 00084 if (reg->onatoms.getIDByAddress(lit.address).isGuardAuxiliary()) continue; 00085 00086 const OrdinaryAtom& atom = reg->onatoms.getByID(lit); 00087 00088 std::set<ID> distinctVar; 00089 int var = 0; 00090 BOOST_FOREACH (ID p, atom.tuple) { 00091 if (p.isVariableTerm()) { 00092 if (std::find(distinctVar.begin(), distinctVar.end(), p) == distinctVar.end()) { 00093 distinctVar.insert(p); 00094 var++; 00095 } 00096 } 00097 } 00098 00099 if (var > maxBoundVariables) { 00100 maxBoundVariables = var; 00101 watchedLit = lit; 00102 } 00103 } 00104 if (watchedLit == ID_FAIL) { 00105 DBGLOG(DBG, "Skipping nogood " << i << " because it contains only guard atoms"); 00106 continue; 00107 } 00108 00109 // watch the atom and the corresponding nogood 00110 DBGLOG(DBG, "Watching literal " << watchedLit << " in nogood " << i); 00111 const OrdinaryAtom& watchedAtom = reg->onatoms.getByAddress(watchedLit.address); 00112 00113 // For each atom A of the program, check if the watched literal unifies with A 00114 bm::bvector<>::enumerator en = agp.getProgramMask()->getStorage().first(); 00115 bm::bvector<>::enumerator en_end = agp.getProgramMask()->getStorage().end(); 00116 00117 DBGLOG(DBG, "Searching for unifying program atoms"); 00118 while (en < en_end) { 00119 00120 DBGLOG(DBG, "Checking atom " << *en); 00121 00122 const OrdinaryAtom& currentAtom = reg->ogatoms.getByAddress(*en); 00123 if (currentAtom.unifiesWith(watchedAtom, reg)) { 00124 Nogood instantiatedNG; 00125 ng.match(reg, reg->ogatoms.getIDByAddress(*en), instantiatedNG); 00126 DBGLOG(DBG, "Instantiated " << instantiatedNG.getStringRepresentation(reg) << " from " << ng.getStringRepresentation(reg)); 00127 00128 // check if the instance of the nogood contains a ground literal which does not appear in the program 00129 bool relevant = true; 00130 Nogood simplifiedNG; 00131 BOOST_FOREACH (ID lit, instantiatedNG) { 00132 if (lit.isOrdinaryGroundAtom() && !reg->ogatoms.getIDByAddress(lit.address).isAuxiliary() && !agp.getProgramMask()->getFact(lit.address)) { 00133 if (!lit.isNaf()) { 00134 // can never be true --> remove whole instance 00135 #ifndef NDEBUG 00136 std::string str = RawPrinter::toString(reg, lit); 00137 DBGLOG(DBG, "Removing because negative " << str << " can never be true"); 00138 #endif 00139 relevant = false; 00140 break; 00141 } 00142 else { 00143 // is always true --> remove literal 00144 } 00145 } 00146 else { 00147 // might be true --> keep literal 00148 simplifiedNG.insert(lit); 00149 } 00150 } 00151 00152 if (relevant) { 00153 if (simplifiedNG.isGround()) { 00154 DBGLOG(DBG, "Keeping ground nogood " << simplifiedNG.getStringRepresentation(reg)); 00155 destination->addNogood(simplifiedNG); 00156 } 00157 else { 00158 DBGLOG(DBG, "Keeping nonground nogood " << simplifiedNG.getStringRepresentation(reg)); 00159 watched->addNogood(simplifiedNG); 00160 } 00161 } 00162 else { 00163 DBGLOG(DBG, "Removing nogood " << simplifiedNG.getStringRepresentation(reg)); 00164 } 00165 } 00166 00167 en++; 00168 } 00169 00170 } 00171 DBGLOG(DBG, "Finished updating"); 00172 instantiatedNongroundNogoodsIndex = max; 00173 } 00174 00175 00176 void ImmediateNogoodGrounder::resetWatched(SimpleNogoodContainerPtr watched) 00177 { 00178 NogoodGrounder::resetWatched(watched); 00179 instantiatedNongroundNogoodsIndex = 0; 00180 } 00181 00182 00183 LazyNogoodGrounder::LazyNogoodGrounder(RegistryPtr reg, SimpleNogoodContainerPtr watched, SimpleNogoodContainerPtr destination, AnnotatedGroundProgram& agp) : 00184 NogoodGrounder(reg, watched, destination, agp), watchedNogoodsCount(0) 00185 { 00186 } 00187 00188 00189 void LazyNogoodGrounder::update(InterpretationConstPtr partialInterpretation, InterpretationConstPtr factWasSet, InterpretationConstPtr changed) 00190 { 00191 00192 if (!factWasSet) return; 00193 00194 // Watch for all new nonground nogoods the literal which binds the highest number of variables 00195 DBGLOG(DBG, "Updating watches of nonground nogoods"); 00196 int max = watched->getNogoodCount(); 00197 if (watchedNogoodsCount >= max) watchedNogoodsCount = 0; 00198 DBGLOG(DBG, "Updating nogood grounder from " << watchedNogoodsCount << " to " << max); 00199 for (int i = watchedNogoodsCount; i < max; ++i) { 00200 Nogood ng = watched->getNogood(i); 00201 DBGLOG(DBG, "Checking nogood " << ng.getStringRepresentation(reg)); 00202 if (ng.isGround()) continue; 00203 00204 DBGLOG(DBG, "Searching for watched literal in nogood " << i); 00205 int maxBoundVariables = 0; 00206 ID watchedLit = ID_FAIL; 00207 BOOST_FOREACH (ID lit, ng) { 00208 if (lit.isOrdinaryGroundAtom()) continue; 00209 if (reg->onatoms.getIDByAddress(lit.address).isGuardAuxiliary()) continue; 00210 00211 const OrdinaryAtom& atom = reg->onatoms.getByID(lit); 00212 00213 std::set<ID> distinctVar; 00214 int var = 0; 00215 BOOST_FOREACH (ID p, atom.tuple) { 00216 if (p.isVariableTerm()) { 00217 if (std::find(distinctVar.begin(), distinctVar.end(), p) == distinctVar.end()) { 00218 distinctVar.insert(p); 00219 var++; 00220 } 00221 } 00222 } 00223 00224 if (var > maxBoundVariables) { 00225 maxBoundVariables = var; 00226 watchedLit = lit; 00227 } 00228 } 00229 if (watchedLit == ID_FAIL) { 00230 DBGLOG(DBG, "Skipping nogood " << i << " because it contains only guard atoms"); 00231 } 00232 else { 00233 // watch the atom and the corresponding nogood 00234 DBGLOG(DBG, "Watching literal " << watchedLit << " in nogood " << i); 00235 watchedLiterals.push_back(std::pair<ID, int>(watchedLit, i)); 00236 } 00237 } 00238 watchedNogoodsCount = watched->getNogoodCount(); 00239 00240 // For each atom A with changed truth value: go through all watches and check if 00241 // 1. the watched literal unifies with A 00242 // 2. the corresponding clause has not been instantiated for A yet 00243 bm::bvector<>::enumerator en = changed->getStorage().first(); 00244 bm::bvector<>::enumerator en_end = changed->getStorage().end(); 00245 00246 DBGLOG(DBG, "Instantiating nonground nogoods"); 00247 while (en < en_end) { 00248 00249 DBGLOG(DBG, "Instantiating for atom " << *en); 00250 typedef std::pair<ID, int> Pair; 00251 BOOST_FOREACH (Pair p, watchedLiterals) { 00252 DBGLOG(DBG, "Matching nonground nogood " << p.second); 00253 00254 // 2. 00255 if (std::find(alreadyCompared.begin(), alreadyCompared.end(), std::pair<IDAddress, int>(*en, p.second)) != alreadyCompared.end()) continue; 00256 00257 const OrdinaryAtom& currentAtom = reg->ogatoms.getByAddress(*en); 00258 const OrdinaryAtom& watchedAtom = reg->onatoms.getByAddress(p.first.address); 00259 // 1. 00260 if (currentAtom.unifiesWith(watchedAtom, reg)) { 00261 Nogood instantiatedNG; 00262 watched->getNogood(p.second).match(reg, reg->ogatoms.getIDByAddress(*en), instantiatedNG); 00263 DBGLOG(DBG, "Instantiated " << instantiatedNG.getStringRepresentation(reg) << " from " << watched->getNogood(p.second).getStringRepresentation(reg)); 00264 00265 if (instantiatedNG.isGround()) { 00266 destination->addNogood(instantiatedNG); 00267 } 00268 else { 00269 watched->addNogood(instantiatedNG); 00270 } 00271 } 00272 00273 alreadyCompared.insert(std::pair<IDAddress, int>(*en, p.second)); 00274 } 00275 en++; 00276 } 00277 } 00278 00279 00280 void LazyNogoodGrounder::resetWatched(SimpleNogoodContainerPtr watched) 00281 { 00282 NogoodGrounder::resetWatched(watched); 00283 } 00284 00285 00286 DLVHEX_NAMESPACE_END 00287 00288 // vim:expandtab:ts=4:sw=4: 00289 // mode: C++ 00290 // End: