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 00037 00038 #include "dlvhex2/GenuinePlainModelGenerator.h" 00039 #include "dlvhex2/InternalGrounder.h" 00040 #include "dlvhex2/Logger.h" 00041 #include "dlvhex2/Registry.h" 00042 #include "dlvhex2/Printer.h" 00043 #include "dlvhex2/ASPSolver.h" 00044 #include "dlvhex2/ProgramCtx.h" 00045 #include "dlvhex2/PluginInterface.h" 00046 #include "dlvhex2/Benchmarking.h" 00047 #include "dlvhex2/ClaspSolver.h" 00048 00049 #include <boost/foreach.hpp> 00050 00051 DLVHEX_NAMESPACE_BEGIN 00052 00053 GenuinePlainModelGeneratorFactory::GenuinePlainModelGeneratorFactory( 00054 ProgramCtx& ctx, 00055 const ComponentInfo& ci, 00056 ASPSolverManager::SoftwareConfigurationPtr externalEvalConfig): 00057 BaseModelGeneratorFactory(), 00058 externalEvalConfig(externalEvalConfig), 00059 ctx(ctx), 00060 ci(ci), 00061 eatoms(ci.outerEatoms), 00062 idb(), 00063 xidb() 00064 { 00065 RegistryPtr reg = ctx.registry(); 00066 00067 // this model generator can handle: 00068 // components with outer eatoms 00069 // components with inner rules 00070 // components with inner constraints 00071 // this model generator CANNOT handle: 00072 // components with inner eatoms 00073 00074 assert(ci.innerEatoms.empty()); 00075 00076 // copy rules and constraints to idb 00077 // TODO we do not need this except for debugging 00078 idb.reserve(ci.innerRules.size() + ci.innerConstraints.size()); 00079 idb.insert(idb.end(), ci.innerRules.begin(), ci.innerRules.end()); 00080 idb.insert(idb.end(), ci.innerConstraints.begin(), ci.innerConstraints.end()); 00081 00082 // transform original innerRules and innerConstraints 00083 // to xidb with only auxiliaries 00084 xidb.reserve(ci.innerRules.size() + ci.innerConstraints.size()); 00085 std::back_insert_iterator<std::vector<ID> > inserter(xidb); 00086 std::transform(ci.innerRules.begin(), ci.innerRules.end(), 00087 inserter, boost::bind( 00088 &GenuinePlainModelGeneratorFactory::convertRule, this, ctx, _1)); 00089 std::transform(ci.innerConstraints.begin(), ci.innerConstraints.end(), 00090 inserter, boost::bind( 00091 &GenuinePlainModelGeneratorFactory::convertRule, this, ctx, _1)); 00092 00093 #ifndef NDEBUG 00094 { 00095 { 00096 std::ostringstream s; 00097 RawPrinter printer(s,ctx.registry()); 00098 printer.printmany(idb," "); 00099 DBGLOG(DBG,"GenuinePlainModelGeneratorFactory got idb " << s.str()); 00100 } 00101 { 00102 std::ostringstream s; 00103 RawPrinter printer(s,ctx.registry()); 00104 printer.printmany(xidb," "); 00105 DBGLOG(DBG,"GenuinePlainModelGeneratorFactory got xidb " << s.str()); 00106 } 00107 } 00108 #endif 00109 } 00110 00111 00112 std::ostream& GenuinePlainModelGeneratorFactory::print( 00113 std::ostream& o) const 00114 { 00115 RawPrinter printer(o, ctx.registry()); 00116 if( !eatoms.empty() ) { 00117 printer.printmany(eatoms,","); 00118 } 00119 if( !xidb.empty() ) { 00120 printer.printmany(xidb,"\n"); 00121 } 00122 return o; 00123 } 00124 00125 00126 GenuinePlainModelGenerator::GenuinePlainModelGenerator( 00127 Factory& factory, 00128 InterpretationConstPtr input): 00129 BaseModelGenerator(input), 00130 factory(factory) 00131 { 00132 DLVHEX_BENCHMARK_REGISTER_AND_SCOPE(sidconstruct, "genuine plain mg construction"); 00133 RegistryPtr reg = factory.ctx.registry(); 00134 00135 // create new interpretation as copy 00136 Interpretation::Ptr newint; 00137 if( input == 0 ) { 00138 // empty construction 00139 newint.reset(new Interpretation(reg)); 00140 } 00141 else { 00142 // copy construction 00143 newint.reset(new Interpretation(*input)); 00144 } 00145 00146 // augment input with edb 00147 newint->add(*factory.ctx.edb); 00148 00149 // remember facts so far (we have to remove these from any output) 00150 InterpretationConstPtr mask(new Interpretation(*newint)); 00151 00152 // manage outer external atoms 00153 if( !factory.eatoms.empty() ) { 00154 DLVHEX_BENCHMARK_REGISTER_AND_SCOPE(sidhexground, "HEX grounder time"); 00155 00156 // augment input with result of external atom evaluation 00157 // use newint as input and as output interpretation 00158 IntegrateExternalAnswerIntoInterpretationCB cb(newint); 00159 evaluateExternalAtoms(factory.ctx, factory.eatoms, newint, cb); 00160 DLVHEX_BENCHMARK_REGISTER(sidcountexternalanswersets, 00161 "outer eatom computations"); 00162 DLVHEX_BENCHMARK_COUNT(sidcountexternalanswersets,1); 00163 } 00164 00165 // store in model generator and store as const 00166 postprocessedInput = newint; 00167 00168 OrdinaryASPProgram program(reg, factory.xidb, postprocessedInput, factory.ctx.maxint, mask); 00169 00170 solver = GenuineSolver::getInstance(factory.ctx, program); 00171 #if 0 00172 { 00173 // Input: a :- fr. b v b2. fr :- b. 00174 // Expected result: { { a, fr, b }, { b2 } } 00175 OrdinaryASPProgram program(reg, std::vector<ID>(), postprocessedInput, factory.ctx.maxint, mask); 00176 00177 int r = 0; 00178 BOOST_FOREACH (ID id, factory.xidb) { 00179 std::cout << (r++) << printToString<RawPrinter>(id, reg) << std::endl; 00180 } 00181 00182 // add first 11 rules 00183 program.idb.push_back(factory.xidb[11]); 00184 program.idb.push_back(factory.xidb[12]); 00185 program.idb.push_back(factory.xidb[0]); 00186 program.idb.push_back(factory.xidb[3]); 00187 program.idb.push_back(factory.xidb[1]); 00188 program.idb.push_back(factory.xidb[2]); 00189 program.idb.push_back(factory.xidb[4]); 00190 program.idb.push_back(factory.xidb[5]); 00191 program.idb.push_back(factory.xidb[13]); 00192 program.idb.push_back(factory.xidb[14]); 00193 program.idb.push_back(factory.xidb[17]); 00194 00195 // freeze all body vars 00196 std::vector<ID> ass; 00197 InterpretationPtr frozen(new Interpretation(reg)); 00198 for (int i = 2; i < program.idb.size(); ++i) { 00199 ID id = program.idb[i]; 00200 const Rule& rule = reg->rules.getByID(id); 00201 if (rule.body.size() > 0) { 00202 frozen->setFact(rule.body[0].address); 00203 ass.push_back(ID::nafLiteralFromAtom(ID::atomFromLiteral(rule.body[0]))); 00204 } 00205 } 00206 00207 // solve 00208 GenuineGroundSolverPtr solver = GenuineGroundSolver::getInstance(factory.ctx, program, frozen); 00209 solver->restartWithAssumptions(ass); 00210 InterpretationConstPtr intr; 00211 std::cout << "It 1" << std::endl; 00212 while (!!(intr = solver->getNextModel())) { 00213 std::cout << "Model: " << *intr << std::endl; 00214 } 00215 00216 // add remaining 7 rules 00217 std::vector<ID> idb1; 00218 idb1.push_back(factory.xidb[6]); 00219 idb1.push_back(factory.xidb[7]); 00220 idb1.push_back(factory.xidb[8]); 00221 idb1.push_back(factory.xidb[9]); 00222 idb1.push_back(factory.xidb[10]); 00223 idb1.push_back(factory.xidb[15]); 00224 idb1.push_back(factory.xidb[16]); 00225 00226 frozen->clear(); 00227 frozen->setFact(reg->rules.getByID(factory.xidb[7]).body[0].address); ass.push_back(ID::nafLiteralFromAtom(ID::atomFromLiteral(reg->rules.getByID(factory.xidb[7]).body[0]))); 00228 frozen->setFact(reg->rules.getByID(factory.xidb[8]).body[0].address); ass.push_back(ID::nafLiteralFromAtom(ID::atomFromLiteral(reg->rules.getByID(factory.xidb[8]).body[0]))); 00229 frozen->setFact(reg->rules.getByID(factory.xidb[15]).body[0].address); ass.push_back(ID::nafLiteralFromAtom(ID::atomFromLiteral(reg->rules.getByID(factory.xidb[15]).body[0]))); 00230 frozen->setFact(reg->rules.getByID(factory.xidb[10]).body[0].address); ass.push_back(ID::nafLiteralFromAtom(ID::atomFromLiteral(reg->rules.getByID(factory.xidb[10]).body[0]))); 00231 00232 OrdinaryASPProgram p1(reg, idb1, postprocessedInput, factory.ctx.maxint, mask); 00233 solver->addProgram(AnnotatedGroundProgram(factory.ctx, p1), frozen); 00234 00235 for (int i = 0; i < ass.size(); ++i) { 00236 if (ass[i] == ID::nafLiteralFromAtom(reg->rules.getByID(factory.xidb[15]).head[0])) { 00237 ass.erase(ass.begin() + i); 00238 break; 00239 } 00240 } 00241 std::vector<ID> idb2; 00242 OrdinaryASPProgram p2(reg, idb2, postprocessedInput, factory.ctx.maxint, mask); 00243 solver->addProgram(AnnotatedGroundProgram(factory.ctx, p2), frozen); 00244 00245 solver->restartWithAssumptions(ass); 00246 std::cout << "It 2" << std::endl; 00247 while (!!(intr = solver->getNextModel())) { 00248 std::cout << "Model: " << *intr << std::endl; 00249 } 00250 } 00251 #endif 00252 } 00253 00254 00255 GenuinePlainModelGenerator::~GenuinePlainModelGenerator() 00256 { 00257 DBGLOG(DBG, "Final Statistics:" << std::endl << solver->getStatistics()); 00258 } 00259 00260 00261 GenuinePlainModelGenerator::InterpretationPtr 00262 GenuinePlainModelGenerator::generateNextModel() 00263 { 00264 if (solver == GenuineSolverPtr()) { 00265 return InterpretationPtr(); 00266 } 00267 00268 RegistryPtr reg = factory.ctx.registry(); 00269 00270 DLVHEX_BENCHMARK_REGISTER_AND_SCOPE(sidhexsolve, "HEX solver time"); 00271 00272 // Search space pruning: the idea is to set the current global optimum as upper limit in the solver instance (of this unit) to eliminate interpretations with higher costs. 00273 // Note that this optimization is conservative such that the algorithm remains complete even when the program is split. Because costs can be only positive, 00274 // if the costs of a partial model are greater than the current global optimum then also any completion of this partial model (by combining it with other units) 00275 // would be non-optimal. 00276 if (factory.ctx.config.getOption("OptimizationByBackend")) solver->setOptimum(factory.ctx.currentOptimum); 00277 InterpretationPtr modelCandidate = solver->getNextModel(); 00278 00279 DBGLOG(DBG, "Statistics:" << std::endl << solver->getStatistics()); 00280 return modelCandidate; 00281 } 00282 00283 00284 DLVHEX_NAMESPACE_END 00285 00286 // vim:expandtab:ts=4:sw=4: 00287 // mode: C++ 00288 // End: