dlvhex  2.5.0
src/PlainModelGenerator.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                           // HAVE_CONFIG_H
00037 
00038 #define DLVHEX_BENCHMARK
00039 
00040 #include "dlvhex2/PlainModelGenerator.h"
00041 #include "dlvhex2/Logger.h"
00042 #include "dlvhex2/Registry.h"
00043 #include "dlvhex2/Printer.h"
00044 #include "dlvhex2/ASPSolver.h"
00045 #include "dlvhex2/ProgramCtx.h"
00046 #include "dlvhex2/PluginInterface.h"
00047 #include "dlvhex2/Benchmarking.h"
00048 
00049 #include <boost/foreach.hpp>
00050 
00051 DLVHEX_NAMESPACE_BEGIN
00052 
00053 PlainModelGeneratorFactory::PlainModelGeneratorFactory(
00054 ProgramCtx& ctx,
00055 const ComponentInfo& ci,
00056 ASPSolverManager::SoftwareConfigurationPtr externalEvalConfig):
00057 BaseModelGeneratorFactory(),
00058 externalEvalConfig(externalEvalConfig),
00059 ctx(ctx),
00060 eatoms(ci.outerEatoms),
00061 idb(),
00062 xidb()
00063 {
00064     RegistryPtr reg = ctx.registry();
00065 
00066     // this model generator can handle:
00067     // components with outer eatoms
00068     // components with inner rules
00069     // components with inner constraints
00070     // this model generator CANNOT handle:
00071     // components with inner eatoms
00072 
00073     assert(ci.innerEatoms.empty());
00074 
00075     // copy rules and constraints to idb
00076     // TODO we do not need this except for debugging
00077     idb.reserve(ci.innerRules.size() + ci.innerConstraints.size());
00078     idb.insert(idb.end(), ci.innerRules.begin(), ci.innerRules.end());
00079     idb.insert(idb.end(), ci.innerConstraints.begin(), ci.innerConstraints.end());
00080 
00081     // transform original innerRules and innerConstraints
00082     // to xidb with only auxiliaries
00083     xidb.reserve(ci.innerRules.size() + ci.innerConstraints.size());
00084     std::back_insert_iterator<std::vector<ID> > inserter(xidb);
00085     std::transform(ci.innerRules.begin(), ci.innerRules.end(),
00086         inserter, boost::bind(
00087         &PlainModelGeneratorFactory::convertRule, this, ctx, _1));
00088     std::transform(ci.innerConstraints.begin(), ci.innerConstraints.end(),
00089         inserter, boost::bind(
00090         &PlainModelGeneratorFactory::convertRule, this, ctx, _1));
00091 
00092     #ifndef NDEBUG
00093     {
00094         {
00095             std::ostringstream s;
00096             RawPrinter printer(s,ctx.registry());
00097             printer.printmany(idb," ");
00098             DBGLOG(DBG,"PlainModelGeneratorFactory got idb " << s.str());
00099         }
00100         {
00101             std::ostringstream s;
00102             RawPrinter printer(s,ctx.registry());
00103             printer.printmany(xidb," ");
00104             DBGLOG(DBG,"PlainModelGeneratorFactory got xidb " << s.str());
00105         }
00106     }
00107     #endif
00108 }
00109 
00110 
00111 std::ostream& PlainModelGeneratorFactory::print(
00112 std::ostream& o) const
00113 {
00114     RawPrinter printer(o, ctx.registry());
00115     o << "outer eatoms:" << std::endl;
00116     if( !eatoms.empty() ) {
00117         printer.printmany(eatoms,"\n");
00118     }
00119     o << "xidb:" << std::endl;
00120     if( !xidb.empty() ) {
00121         printer.printmany(xidb,"\n");
00122     }
00123     return o;
00124 }
00125 
00126 
00127 PlainModelGenerator::PlainModelGenerator(
00128 Factory& factory,
00129 InterpretationConstPtr input):
00130 BaseModelGenerator(input),
00131 factory(factory)
00132 {
00133 }
00134 
00135 
00136 PlainModelGenerator::InterpretationPtr
00137 PlainModelGenerator::generateNextModel()
00138 {
00139     RegistryPtr reg = factory.ctx.registry();
00140     if( currentResults == 0 ) {
00141         do {                     // breakout possibility
00142             // we need to create currentResults
00143 
00144             // create new interpretation as copy
00145             Interpretation::Ptr newint;
00146             if( input == 0 ) {
00147                 // empty construction
00148                 newint.reset(new Interpretation(reg));
00149             }
00150             else {
00151                 // copy construction
00152                 newint.reset(new Interpretation(*input));
00153             }
00154 
00155             // augment input with edb
00156             newint->add(*factory.ctx.edb);
00157 
00158             // remember facts so far (we have to remove these from any output)
00159             InterpretationConstPtr mask(new Interpretation(*newint));
00160 
00161             // manage outer external atoms
00162             if( !factory.eatoms.empty() ) {
00163                 // augment input with result of external atom evaluation
00164                 // use newint as input and as output interpretation
00165                 IntegrateExternalAnswerIntoInterpretationCB cb(newint);
00166                 evaluateExternalAtoms(factory.ctx, factory.eatoms, newint, cb);
00167                 DLVHEX_BENCHMARK_REGISTER(sidcountexternalanswersets,
00168                     "outer eatom computations");
00169                 DLVHEX_BENCHMARK_COUNT(sidcountexternalanswersets,1);
00170 
00171                 if( factory.xidb.empty() ) {
00172                     // we only have eatoms -> return singular result
00173 
00174                     // remove EDB and direct input from newint
00175                     // (keep local models as small as possible)
00176                     newint->getStorage() -= mask->getStorage();
00177 
00178                     PreparedResults* pr = new PreparedResults;
00179                     currentResults.reset(pr);
00180                     pr->add(AnswerSetPtr(new AnswerSet(newint)));
00181                     break;
00182                 }
00183             }
00184 
00185             // store in model generator and store as const
00186             postprocessedInput = newint;
00187 
00188             DLVHEX_BENCHMARK_REGISTER_AND_START(sidaspsolve,
00189                 "initiating external solver");
00190             OrdinaryASPProgram program(reg,
00191                 factory.xidb, postprocessedInput, factory.ctx.maxint, mask);
00192             ASPSolverManager mgr;
00193             currentResults = mgr.solve(*factory.externalEvalConfig, program);
00194             DLVHEX_BENCHMARK_STOP(sidaspsolve);
00195         }
00196         while(false);            // end of breakout possibility
00197     }
00198 
00199     assert(currentResults != 0);
00200     AnswerSet::Ptr ret = currentResults->getNextAnswerSet();
00201     if( ret == 0 ) {
00202         currentResults.reset();
00203         // the following is just for freeing memory early
00204         postprocessedInput.reset();
00205         return InterpretationPtr();
00206     }
00207     DLVHEX_BENCHMARK_REGISTER(sidcountplainanswersets, "PlainMG answer sets");
00208     DLVHEX_BENCHMARK_COUNT(sidcountplainanswersets,1);
00209 
00210     return ret->interpretation;
00211 }
00212 
00213 
00214 DLVHEX_NAMESPACE_END
00215 
00216 // vim:expandtab:ts=4:sw=4:
00217 // mode: C++
00218 // End: