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 #ifdef HAVE_CONFIG_H 00035 #include "config.h" 00036 #endif // HAVE_CONFIG_H 00037 00038 #define DLVHEX_BENCHMARK 00039 00040 #include "dlvhex2/GuessAndCheckModelGenerator.h" 00041 #include "dlvhex2/Logger.h" 00042 #include "dlvhex2/Registry.h" 00043 #include "dlvhex2/Printer.h" 00044 #include "dlvhex2/OrdinaryASPProgram.h" 00045 #include "dlvhex2/OrdinaryASPSolver.h" 00046 #include "dlvhex2/ASPSolver.h" 00047 #include "dlvhex2/ASPSolverManager.h" 00048 #include "dlvhex2/ProgramCtx.h" 00049 #include "dlvhex2/PluginInterface.h" 00050 #include "dlvhex2/Benchmarking.h" 00051 00052 #include <bm/bmalgo.h> 00053 00054 #include <boost/foreach.hpp> 00055 00056 DLVHEX_NAMESPACE_BEGIN 00057 00095 namespace 00096 { 00097 00098 class ASMOrdinaryASPSolver; 00099 typedef boost::shared_ptr<ASMOrdinaryASPSolver> 00100 ASMOrdinaryASPSolverPtr; 00101 00102 class ASMOrdinaryASPSolver: 00103 public OrdinaryASPSolver 00104 { 00105 protected: 00106 ASPSolverManager::ResultsPtr results; 00107 InterpretationConstPtr mask; 00108 00109 ASMOrdinaryASPSolver(ProgramCtx& ctx, OrdinaryASPProgram& program): 00110 mask(program.mask) { 00111 ASPSolverManager mgr; 00112 results = mgr.solve(*ctx.aspsoftware, program); 00113 } 00114 00115 public: 00116 static ASMOrdinaryASPSolverPtr getInstance(ProgramCtx& ctx, OrdinaryASPProgram& program) { 00117 return ASMOrdinaryASPSolverPtr(new ASMOrdinaryASPSolver(ctx, program)); 00118 } 00119 00120 // get next model 00121 virtual InterpretationPtr getNextModel() { 00122 AnswerSetPtr as = results->getNextAnswerSet(); 00123 if( !!as ) { 00124 InterpretationPtr answer = InterpretationPtr(new Interpretation(*(as->interpretation))); 00125 if (mask != InterpretationConstPtr()) { 00126 answer->getStorage() -= mask->getStorage(); 00127 } 00128 return answer; 00129 } 00130 else { 00131 return InterpretationPtr(); 00132 } 00133 } 00134 }; 00135 00136 } 00137 00138 00139 // 00140 // the factory 00141 // 00142 00143 WARNING("ASPSolverManager::SoftwareConfigurationPtr externalEvalConfig is already stored in ProgramCtx ... reuse it and remove parameters?") 00144 GuessAndCheckModelGeneratorFactory::GuessAndCheckModelGeneratorFactory( 00145 ProgramCtx& ctx, 00146 const ComponentInfo& ci, 00147 ASPSolverManager::SoftwareConfigurationPtr externalEvalConfig): 00148 FLPModelGeneratorFactoryBase(ctx), 00149 externalEvalConfig(externalEvalConfig), 00150 ctx(ctx), 00151 ci(ci), 00152 outerEatoms(ci.outerEatoms) 00153 { 00154 // this model generator can handle any components 00155 // (and there is quite some room for more optimization) 00156 00157 // just copy all rules and constraints to idb 00158 idb.reserve(ci.innerRules.size() + ci.innerConstraints.size()); 00159 idb.insert(idb.end(), ci.innerRules.begin(), ci.innerRules.end()); 00160 idb.insert(idb.end(), ci.innerConstraints.begin(), ci.innerConstraints.end()); 00161 00162 innerEatoms = ci.innerEatoms; 00163 // create guessing rules "gidb" for innerEatoms in all inner rules and constraints 00164 createEatomGuessingRules(ctx); 00165 // transform original innerRules and innerConstraints to xidb with only auxiliaries 00166 xidb.reserve(ci.innerRules.size() + ci.innerConstraints.size()); 00167 std::back_insert_iterator<std::vector<ID> > inserter(xidb); 00168 std::transform(ci.innerRules.begin(), ci.innerRules.end(), 00169 inserter, boost::bind(&GuessAndCheckModelGeneratorFactory::convertRule, this, ctx, _1)); 00170 std::transform(ci.innerConstraints.begin(), ci.innerConstraints.end(), 00171 inserter, boost::bind(&GuessAndCheckModelGeneratorFactory::convertRule, this, ctx, _1)); 00172 00173 // transform xidb for flp calculation 00174 if (ctx.config.getOption("FLPCheck")) createFLPRules(); 00175 00176 // output rules 00177 { 00178 std::ostringstream s; 00179 print(s, true); 00180 LOG(DBG,"GuessAndCheckModelGeneratorFactory(): " << s.str()); 00181 } 00182 } 00183 00184 00185 GuessAndCheckModelGeneratorFactory::ModelGeneratorPtr 00186 GuessAndCheckModelGeneratorFactory::createModelGenerator(InterpretationConstPtr input) 00187 { 00188 return ModelGeneratorPtr(new GuessAndCheckModelGenerator(*this, input)); 00189 } 00190 00191 00192 std::ostream& GuessAndCheckModelGeneratorFactory::print( 00193 std::ostream& o) const 00194 { 00195 return print(o, false); 00196 } 00197 00198 00199 std::ostream& GuessAndCheckModelGeneratorFactory::print( 00200 std::ostream& o, bool verbose) const 00201 { 00202 // item separator 00203 std::string isep("\n"); 00204 // group separator 00205 std::string gsep("\n"); 00206 if( verbose ) { 00207 isep = "\n"; 00208 gsep = "\n"; 00209 } 00210 RawPrinter printer(o, ctx.registry()); 00211 if( !outerEatoms.empty() ) { 00212 o << "outer Eatoms={" << gsep; 00213 printer.printmany(outerEatoms,isep); 00214 o << gsep << "}" << gsep; 00215 } 00216 if( !innerEatoms.empty() ) { 00217 o << "inner Eatoms={" << gsep; 00218 printer.printmany(innerEatoms,isep); 00219 o << gsep << "}" << gsep; 00220 } 00221 if( !gidb.empty() ) { 00222 o << "gidb={" << gsep; 00223 printer.printmany(gidb,isep); 00224 o << gsep << "}" << gsep; 00225 } 00226 if( !idb.empty() ) { 00227 o << "idb={" << gsep; 00228 printer.printmany(idb,isep); 00229 o << gsep << "}" << gsep; 00230 } 00231 if( !xidb.empty() ) { 00232 o << "xidb={" << gsep; 00233 printer.printmany(xidb,isep); 00234 o << gsep << "}" << gsep; 00235 } 00236 if( !xidbflphead.empty() ) { 00237 o << "xidbflphead={" << gsep; 00238 printer.printmany(xidbflphead,isep); 00239 o << gsep << "}" << gsep; 00240 } 00241 if( !xidbflpbody.empty() ) { 00242 o << "xidbflpbody={" << gsep; 00243 printer.printmany(xidbflpbody,isep); 00244 o << gsep << "}" << gsep; 00245 } 00246 return o; 00247 } 00248 00249 00250 // 00251 // the model generator 00252 // 00253 00254 GuessAndCheckModelGenerator::GuessAndCheckModelGenerator( 00255 Factory& factory, 00256 InterpretationConstPtr input): 00257 FLPModelGeneratorBase(factory, input), 00258 factory(factory) 00259 { 00260 DBGLOG(DBG, "GnC-ModelGenerator is instantiated for a " << (factory.ci.disjunctiveHeads ? "" : "non-") << "disjunctive component"); 00261 00262 RegistryPtr reg = factory.reg; 00263 00264 // create new interpretation as copy 00265 InterpretationPtr postprocInput; 00266 if( input == 0 ) { 00267 // empty construction 00268 postprocInput.reset(new Interpretation(reg)); 00269 } 00270 else { 00271 // copy construction 00272 postprocInput.reset(new Interpretation(*input)); 00273 } 00274 00275 // augment input with edb 00276 WARNING("perhaps we can pass multiple partially preprocessed input edb's to the external solver and save a lot of processing here") 00277 postprocInput->add(*factory.ctx.edb); 00278 00279 // remember which facts we must remove 00280 mask.reset(new Interpretation(*postprocInput)); 00281 00282 // manage outer external atoms 00283 if( !factory.outerEatoms.empty() ) { 00284 // augment input with result of external atom evaluation 00285 // use newint as input and as output interpretation 00286 IntegrateExternalAnswerIntoInterpretationCB cb(postprocInput); 00287 evaluateExternalAtoms(factory.ctx, 00288 factory.outerEatoms, postprocInput, cb); 00289 DLVHEX_BENCHMARK_REGISTER(sidcountexternalatomcomps, 00290 "outer eatom computations"); 00291 DLVHEX_BENCHMARK_COUNT(sidcountexternalatomcomps,1); 00292 00293 assert(!factory.xidb.empty() && 00294 "the guess and check model generator is not required for " 00295 "non-idb components! (use plain)"); 00296 } 00297 00298 // assign to const member -> stays the same from here no! 00299 postprocessedInput = postprocInput; 00300 00301 // start evaluate edb+xidb+gidb 00302 { 00303 DBGLOG(DBG,"evaluating guessing program"); 00304 // no mask 00305 OrdinaryASPProgram program(reg, factory.xidb, postprocessedInput, factory.ctx.maxint); 00306 // append gidb to xidb 00307 program.idb.insert(program.idb.end(), factory.gidb.begin(), factory.gidb.end()); 00308 ASPSolverManager mgr; 00309 guessres = mgr.solve(*factory.externalEvalConfig, program); 00310 } 00311 } 00312 00313 00314 InterpretationPtr GuessAndCheckModelGenerator::generateNextModel() 00315 { 00316 RegistryPtr reg = factory.reg; 00317 00318 // now we have postprocessed input in postprocessedInput 00319 DLVHEX_BENCHMARK_REGISTER_AND_SCOPE(sidgcsolve, "guess and check loop"); 00320 00321 InterpretationPtr modelCandidate; 00322 do { 00323 AnswerSetPtr guessas = guessres->getNextAnswerSet(); 00324 if( !guessas ) 00325 return InterpretationPtr(); 00326 modelCandidate = guessas->interpretation; 00327 00328 DBGLOG_SCOPE(DBG,"gM", false); 00329 DBGLOG(DBG,"= got guess model " << *modelCandidate); 00330 00331 DBGLOG(DBG, "doing compatibility check for model candidate " << *modelCandidate); 00332 assert(!factory.ctx.config.getOption("ExternalLearning") && 00333 "cannot use external learning in (non-genuine) GuessAndCheckModelGenerator"); 00334 bool compatible = isCompatibleSet( 00335 modelCandidate, postprocessedInput, factory.ctx, 00336 SimpleNogoodContainerPtr()); 00337 DBGLOG(DBG, "Compatible: " << compatible); 00338 if (!compatible) continue; 00339 00340 // FLP check 00341 if (factory.ctx.config.getOption("FLPCheck")) { 00342 DBGLOG(DBG, "FLP Check"); 00343 if( !isSubsetMinimalFLPModel<ASMOrdinaryASPSolver>( 00344 modelCandidate, postprocessedInput, factory.ctx) ) 00345 continue; 00346 } 00347 else { 00348 DBGLOG(DBG, "Skipping FLP Check"); 00349 } 00350 00351 // remove edb and the guess (from here we don't need the guess anymore) 00352 modelCandidate->getStorage() -= factory.gpMask.mask()->getStorage(); 00353 modelCandidate->getStorage() -= factory.gnMask.mask()->getStorage(); 00354 00355 modelCandidate->getStorage() -= mask->getStorage(); 00356 00357 DBGLOG(DBG,"= final model candidate " << *modelCandidate); 00358 return modelCandidate; 00359 } 00360 while(true); 00361 } 00362 00363 00364 DLVHEX_NAMESPACE_END 00365 00366 00367 // vim:expandtab:ts=4:sw=4: 00368 // mode: C++ 00369 // End: