dlvhex  2.5.0
src/GenuinePlainModelGenerator.cpp
Go to the documentation of this file.
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: