dlvhex  2.5.0
include/dlvhex2/OnlineModelBuilder.h
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 #ifndef ONLINE_MODEL_BUILDER_HPP_INCLUDED__23092010
00035 #define ONLINE_MODEL_BUILDER_HPP_INCLUDED__23092010
00036 
00037 #include "dlvhex2/PlatformDefinitions.h"
00038 #include "dlvhex2/Logger.h"
00039 #include "dlvhex2/ModelGenerator.h"
00040 #include "dlvhex2/ModelBuilder.h"
00041 
00042 #include <iomanip>
00043 
00044 DLVHEX_NAMESPACE_BEGIN
00045 
00047 template<typename EvalGraphT>
00048 class OnlineModelBuilder:
00049 public ModelBuilder<EvalGraphT>
00050 {
00051     // types
00052     public:
00053         typedef ModelBuilder<EvalGraphT>
00054             Base;
00055         typedef OnlineModelBuilder<EvalGraphT>
00056             Self;
00057 
00058         // import typedefs from base class
00059         typedef typename Base::MyEvalGraph
00060             MyEvalGraph;
00061         typedef typename Base::EvalUnit
00062             EvalUnit;
00063         typedef typename Base::EvalUnitPropertyBundle
00064             EvalUnitPropertyBundle;
00065         typedef typename Base::Interpretation
00066             Interpretation;
00067         typedef typename Base::InterpretationPtr
00068             InterpretationPtr;
00069         typedef typename Base::MyModelGraph
00070             MyModelGraph;
00071         typedef typename Base::Model
00072             Model;
00073         typedef typename Base::OptionalModel
00074             OptionalModel;
00075 
00076         // import members from base class
00077         using Base::eg;
00078         using Base::mg;
00079 
00080         // our own typedefs
00081         typedef typename MyEvalGraph::EvalUnitDep
00082             EvalUnitDep;
00083         typedef typename MyEvalGraph::PredecessorIterator
00084             EvalUnitPredecessorIterator;
00085 
00086         typedef typename MyModelGraph::ModelDep
00087             ModelDep;
00088         typedef typename MyModelGraph::ModelPropertyBundle
00089             ModelPropertyBundle;
00090         typedef typename MyModelGraph::ModelList
00091             ModelList;
00092         typedef boost::optional<typename MyModelGraph::ModelList::const_iterator>
00093             OptionalModelListIterator;
00094         typedef typename MyModelGraph::PredecessorIterator
00095             ModelPredecessorIterator;
00096         typedef typename MyModelGraph::SuccessorIterator
00097             ModelSuccessorIterator;
00098         typedef boost::optional<typename MyModelGraph::SuccessorIterator>
00099             OptionalModelSuccessorIterator;
00100 
00104         struct EvalUnitModelBuildingProperties
00105         {
00106             // storage
00107 
00108             // currently running model generator
00109             // (such a model generator is bound to some input model)
00110             // (it is reinitialized for each new input model)
00111             typename ModelGeneratorBase<Interpretation>::Ptr currentmg;
00112 
00113             bool needInput;
00114 
00115             unsigned orefcount;
00116 
00117             protected:
00119                 OptionalModel imodel;
00120 
00121             public:
00123                 OptionalModelSuccessorIterator currentisuccessor;
00124 
00126                 EvalUnitModelBuildingProperties():
00127                 currentmg(), needInput(false), orefcount(0),
00128                     imodel(), currentisuccessor()
00129                     {}
00132                 inline const OptionalModel& getIModel() const
00133                 {
00134                     return imodel;
00135                 }
00136 
00139                 void setIModel(OptionalModel m) {
00140                     // we can change the imodel iff currentmg is null
00141                     assert(!(!!m && imodel != m && currentmg != 0));
00142                     // log warning if we unset the imodel if currentmg is not null
00143                     if( !m && imodel != m && currentmg != 0 ) {
00144                         LOG(WARNING,"WARNING: unsetting imodel while currentmg is null -> unsetting currentmg too");
00145                         currentmg.reset();
00146                     }
00147                     imodel = m;
00148                 }
00149 
00152                 bool hasOModel() const
00153                     { return !!currentisuccessor; }
00154         };
00155         typedef boost::vector_property_map<EvalUnitModelBuildingProperties>
00156             EvalUnitModelBuildingPropertyMap;
00157 
00162         std::ostream& printEUMBPhelper(
00163             std::ostream& o, const EvalUnitModelBuildingProperties& p) const
00164         {
00165             o <<
00166                 "currentmg = " << std::setw(9) << printptr(p.currentmg) <<
00167                 ", needInput = " << p.needInput <<
00168                 ", orefcount = " << p.orefcount <<
00169                 ", imodel = " << std::setw(9) << printopt(p.getIModel()) <<
00170                 ", currentisuccessor = ";
00171             if( !!p.currentisuccessor )
00172                 o << mg.sourceOf(*p.currentisuccessor.get())
00173                     << " -> "
00174                     << mg.targetOf(*p.currentisuccessor.get());
00175             else
00176                 o << "unset";
00177             return o;
00178         }
00179 
00183         print_container* printEUMBP(
00184             const EvalUnitModelBuildingProperties& p) const
00185         {
00186             return print_function(boost::bind(&Self::printEUMBPhelper, this, _1, p));
00187         }
00188 
00192         Model getOModel(const EvalUnitModelBuildingProperties& p) const
00193         {
00194             assert(!!p.currentisuccessor);
00195             return mg.sourceOf(*p.currentisuccessor.get());
00196         }
00197 
00198     protected:
00201         void clearIModel(Model m) {
00202             mg.propsOf(m).interpretation.reset();
00203         }
00204 
00207         void clearOModel(ModelSuccessorIterator msi) {
00208             mg.propsOf(mg.sourceOf(*msi)).interpretation.reset();
00209         }
00210 
00211     private:
00213         typedef typename EvalGraphT::Observer EvalGraphObserverBase;
00214         class EvalGraphObserver:
00215     public EvalGraphObserverBase
00216     {
00217         public:
00220             EvalGraphObserver(Self& omb): omb(omb) {}
00222             virtual ~EvalGraphObserver() {}
00225             virtual void addUnit(EvalUnit u) {
00226                 DBGLOG(DBG,"observing addUnit(" << u << ")");
00227                 EvalUnitModelBuildingProperties& mbprops =
00228                     omb.mbp[u];
00229                 mbprops.needInput = false;
00230             }
00233             virtual void addDependency(EvalUnitDep d) {
00234                 DBGLOG(DBG,"observing addDependency(" << omb.eg.sourceOf(d) << " -> " << omb.eg.targetOf(d) << ")");
00235                 EvalUnitModelBuildingProperties& mbprops =
00236                     omb.mbp[omb.eg.sourceOf(d)];
00237                 mbprops.needInput = true;
00238             }
00239 
00240         protected:
00242             Self& omb;
00243     };
00244 
00245     // members
00246     protected:
00248         EvalUnitModelBuildingPropertyMap mbp;
00250         boost::shared_ptr<EvalGraphObserver> ego;
00252         bool redundancyElimination;
00254         bool constantSpace;
00255 
00256         // methods
00257     public:
00260         OnlineModelBuilder(ModelBuilderConfig<EvalGraphT>& cfg):
00261         Base(cfg),
00262             mbp(),
00263         // setup observer to do the things below in case EvalGraph is changed
00264         // after the creation of this OnlineModelBuilder
00265             ego(new EvalGraphObserver(*this)),
00266             redundancyElimination(cfg.redundancyElimination),
00267         constantSpace(cfg.constantSpace) {
00268             EvalGraphT& eg = cfg.eg;
00269             // allocate full mbp (plus one unit, as we will likely get an additional vertex)
00270             EvalUnitModelBuildingProperties& mbproptemp = mbp[eg.countEvalUnits()];
00271             (void)mbproptemp;
00272 
00273             // initialize mbp for each vertex in eg
00274             typename EvalGraphT::EvalUnitIterator it, end;
00275             for(boost::tie(it, end) = eg.getEvalUnits(); it != end; ++it) {
00276                 EvalUnit u = *it;
00277                 DBGLOG(DBG,"initializing mbp for unit " << u);
00278                 EvalUnitModelBuildingProperties& mbprops = mbp[u];
00279                 EvalUnitPredecessorIterator it, end;
00280                 boost::tie(it, end) = eg.getPredecessors(u);
00281                 if( it != end )
00282                     mbprops.needInput = true;
00283                 else {
00284                     mbprops.needInput = false;
00285                     assert(!eg.propsOf(u).iproject);
00286                 }
00287             }
00288             eg.addObserver(ego);
00289         }
00290 
00292         virtual ~OnlineModelBuilder() { }
00293 
00294     protected:
00298         Model createIModelFromPredecessorOModels(EvalUnit u);
00299 
00305         OptionalModel advanceOModelForIModel(EvalUnit u);
00309         OptionalModel createNextModel(EvalUnit u);
00314         boost::optional<EvalUnitPredecessorIterator>
00315             ensureModelIncrement(EvalUnit u, EvalUnitPredecessorIterator cursor);
00316 
00319         void removeIModelFromGraphs(Model m);
00320 
00321     public:
00322         // get next input model (projected if projection is configured) at unit u
00323         virtual OptionalModel getNextIModel(EvalUnit u);
00324 
00325         // get next output model (projected if projection is configured) at unit u
00326         virtual OptionalModel getNextOModel(EvalUnit u);
00327 
00328         // debugging methods
00329     public:
00330         virtual void printEvalGraphModelGraph(std::ostream&);
00331         virtual void printModelBuildingPropertyMap(std::ostream&);
00332 };
00333 
00334 template<typename EvalGraphT>
00335 void
00336 OnlineModelBuilder<EvalGraphT>::printEvalGraphModelGraph(std::ostream& o)
00337 {
00338     o << "eval graph/model graph" << std::endl;
00339     typename EvalGraphT::EvalUnitIterator uit, ubegin, uend;
00340     boost::tie(ubegin, uend) = eg.getEvalUnits();
00341     for(uit = ubegin; uit != uend; ++uit) {
00342         std::string indent = "  ";
00343         EvalUnit u = *uit;
00344         std::stringstream s; s << "u " << u << " ";
00345         indent = s.str();
00346         o << indent << "=unit " << std::endl;
00347 
00348         // EvalUnitProjectionProperties
00349         o << indent << "iproject = " << eg.propsOf(u).iproject << " oproject = " << eg.propsOf(u).oproject << std::endl;
00350 
00351         // EvalUnitModelGeneratorFactoryProperties
00352         if( eg.propsOf(u).mgf ) {
00353             o << indent  <<
00354                 "model generator factory = " << printptr(eg.propsOf(u).mgf) <<
00355                 ":" << *eg.propsOf(u).mgf << std::endl;
00356         }
00357         else {
00358             o << indent  <<
00359                 "no model generator factory" << std::endl;
00360         }
00361 
00362         // unit dependencies
00363         typename EvalGraphT::PredecessorIterator pit, pbegin, pend;
00364         boost::tie(pbegin, pend) = eg.getPredecessors(u);
00365         for(pit = pbegin; pit != pend; ++pit) {
00366             o << indent <<
00367                 "-> depends on unit " << eg.targetOf(*pit) <<
00368                 "/join order " << eg.propsOf(*pit).joinOrder << std::endl;
00369         }
00370 
00371         // models
00372         indent += "models ";
00373         for(ModelType t = MT_IN; t <= MT_OUTPROJ; t = static_cast<ModelType>(static_cast<unsigned>(t)+1)) {
00374             const ModelList& modelsAt = mg.modelsAt(u, t);
00375             typename MyModelGraph::ModelList::const_iterator mit;
00376             for(mit = modelsAt.begin(); mit != modelsAt.end(); ++mit) {
00377                 Model m = *mit;
00378                 o << indent <<
00379                     toString(t) << "@" << m << ": " << mg.propsOf(m) << std::endl;
00380                 // model dependencies (preds)
00381                 ModelPredecessorIterator pit, pbegin, pend;
00382                 boost::tie(pbegin, pend) = mg.getPredecessors(m);
00383                 for(pit = pbegin; pit != pend; ++pit) {
00384                     o << indent <<
00385                         "-> depends on model " << mg.targetOf(*pit) <<
00386                         "/join order " << mg.propsOf(*pit).joinOrder << std::endl;
00387                 }
00388                 // model dependencies (succs)
00389                 ModelSuccessorIterator sit, sbegin, send;
00390                 boost::tie(sbegin, send) = mg.getSuccessors(m);
00391                 for(sit = sbegin; sit != send; ++sit) {
00392                     o << indent <<
00393                         "<- input for model  " << mg.sourceOf(*sit) <<
00394                         "/join order " << mg.propsOf(*sit).joinOrder << std::endl;
00395                 }
00396             }
00397             if( modelsAt.empty() )
00398                 o << indent << toString(t) << " empty" << std::endl;
00399         }
00400     }
00401 }
00402 
00403 
00404 template<typename EvalGraphT>
00405 void
00406 OnlineModelBuilder<EvalGraphT>::printModelBuildingPropertyMap(std::ostream& o)
00407 {
00408     o << "model building property map" << std::endl;
00409     typename std::vector<EvalUnitModelBuildingProperties>::const_iterator
00410         it, end;
00411     unsigned u = 0;
00412     it = mbp.storage_begin();
00413     end = mbp.storage_end();
00414     if( it == end ) {
00415         o << "empty" << std::endl;
00416     }
00417     else {
00418         for(; it != end; ++it, ++u) {
00419             const EvalUnitModelBuildingProperties& uprop = *it;
00420             o << " " << u << "=>" << printEUMBP(uprop) << std::endl;
00421         }
00422     }
00423 }
00424 
00425 
00426 template<typename EvalGraphT>
00427 typename OnlineModelBuilder<EvalGraphT>::Model
00428 OnlineModelBuilder<EvalGraphT>::createIModelFromPredecessorOModels(
00429 EvalUnit u)
00430 {
00431                                  // only called from within object -> do not log this ptr
00432     LOG_SCOPE(MODELB,"cIMfPOM",true);
00433     DBGLOG(DBG,"=OnlineModelBuilder<...>::createIModelFromPredecessorOModels(" << u << ")");
00434 
00435     // create vector of dependencies
00436     std::vector<Model> deps;
00437     typename EvalGraphT::PredecessorIterator pit, pend;
00438     boost::tie(pit, pend) = eg.getPredecessors(u);
00439     for(; pit != pend; ++pit) {
00440         EvalUnit pred = eg.targetOf(*pit);
00441         EvalUnitModelBuildingProperties& predmbprops = mbp[pred];
00442         LOG(MODELB,"found predecessor unit " << pred << " with current omodel mbprops: " << printEUMBP(predmbprops));
00443         Model predmodel = getOModel(predmbprops);
00444         deps.push_back(predmodel);
00445     }
00446 
00447     if( redundancyElimination ) {
00448         // check if there is an existing model created from these predecessors
00449         // if yes, just return this model
00450         OptionalModel oexisting = mg.getSuccessorIntersection(u, deps);
00451         if( !!oexisting ) {
00452             LOG(MODELB,"found and will return existing successor imodel " << oexisting.get());
00453             return oexisting.get();
00454         }
00455     }
00456 
00457     // create interpretation
00458     InterpretationPtr pjoin;
00459     if( deps.size() == 1 ) {
00460         // only link
00461         LOG(MODELB,"only one predecessor -> linking to omodel");
00462         pjoin = mg.propsOf(deps.front()).interpretation;
00463         assert(pjoin != 0);
00464     }
00465     else {
00466         // create joined interpretation
00467         LOG(MODELB,"more than one predecessor -> joining omodels");
00468         typename std::vector<Model>::const_iterator it;
00469         for(it = deps.begin(); it != deps.end(); ++it) {
00470             InterpretationPtr predinterpretation = mg.propsOf(*it).interpretation;
00471             DBGLOG(DBG,"predecessor omodel " << *it <<
00472                 " has interpretation " << printptr(predinterpretation) <<
00473                 " with contents " << *predinterpretation);
00474             assert(predinterpretation != 0);
00475             if( pjoin == 0 ) {
00476                 // copy interpretation
00477                 pjoin.reset(new Interpretation(*predinterpretation));
00478             }
00479             else {
00480                 // merge interpretation
00481                 pjoin->add(*predinterpretation);
00482             }
00483             DBGLOG(DBG,"pjoin now has contents " << *pjoin);
00484         }
00485     }
00486 
00487     // create model
00488     Model m = mg.addModel(u, MT_IN, deps);
00489     LOG(MODELB,"returning new MT_IN model " << m);
00490     mg.propsOf(m).interpretation = pjoin;
00491     return m;
00492 }
00493 
00494 
00495 // helper for advanceOModelForIModel
00496 // TODO: comments from hexeval.tex
00497 template<typename EvalGraphT>
00498 boost::optional<typename OnlineModelBuilder<EvalGraphT>::EvalUnitPredecessorIterator>
00499 OnlineModelBuilder<EvalGraphT>::ensureModelIncrement(
00500 EvalUnit u, typename OnlineModelBuilder<EvalGraphT>::EvalUnitPredecessorIterator cursor)
00501 {
00502     LOG_VSCOPE(MODELB,"eMI",u,true);
00503     #ifndef NDEBUG
00504     typename EvalGraphT::EvalUnit ucursor1 =
00505         eg.targetOf(*cursor);
00506     std::ostringstream dbgstr;
00507     dbgstr << "eMI[" << u << "," << ucursor1 << "]";
00508     DBGLOG_SCOPE(MODELB,dbgstr.str(),true);
00509     DBGLOG(DBG,"=OnlineModelBuilder<...>::ensureModelIncrement(" << u << "," << ucursor1 << ")");
00510     #endif
00511 
00512     EvalUnitPredecessorIterator pbegin, pend;
00513     boost::tie(pbegin, pend) = eg.getPredecessors(u);
00514     assert(pbegin != pend);
00515     do {
00516         typename EvalGraphT::EvalUnit ucursor =
00517             eg.targetOf(*cursor);
00518         #ifndef NDEBUG
00519         EvalUnitModelBuildingProperties& ucursor_mbprops =
00520             mbp[ucursor];
00521         DBGLOG(DBG,"ucursor = " << ucursor << " with mbprops = {" << printEUMBP(ucursor_mbprops) << "}");
00522         assert(ucursor_mbprops.hasOModel());
00523         assert(ucursor_mbprops.orefcount >= 1);
00524         #endif
00525 
00526         OptionalModel om = getNextOModel(ucursor);
00527         if( !om ) {
00528             if( cursor == pbegin ) {
00529                 LOG(MODELB,"cannot advance previous, returning null cursor");
00530                 return boost::none;
00531             }
00532             else {
00533                 LOG(MODELB,"trying to advance previous");
00534                 cursor--;
00535             }
00536         }
00537         else
00538             break;
00539     }
00540     while(true);
00541 
00542     #ifndef NDEBUG
00543     typename EvalGraphT::EvalUnit ucursor2 =
00544         eg.targetOf(*cursor);
00545     EvalUnitModelBuildingProperties& ucursor2_mbprops =
00546         mbp[ucursor2];
00547     DBGLOG(DBG,"returning cursor: unit = " << ucursor2 << " with mbprops = {" << printEUMBP(ucursor2_mbprops) << "}");
00548     assert(ucursor2_mbprops.hasOModel());
00549     #endif
00550     return cursor;
00551 }
00552 
00553 
00554 /*
00555  * TODO get documentation from hexeval.tex
00556  */
00557 template<typename EvalGraphT>
00558 typename OnlineModelBuilder<EvalGraphT>::OptionalModel
00559 OnlineModelBuilder<EvalGraphT>::getNextIModel(
00560 EvalUnit u)
00561 {
00562     LOG_VSCOPE(MODELB,"gnIM",u,true);
00563     DBGLOG(DBG,"=OnlineModelBuilder<...>::getNextIModel(" << u << ")");
00564 
00565     #ifndef NDEBUG
00566     if( Logger::Instance().shallPrint(Logger::MODELB) && Logger::Instance().shallPrint(Logger::DBG) )
00567         printModelBuildingPropertyMap(std::cerr);
00568     const EvalUnitPropertyBundle& uprops = eg.propsOf(u);
00569     DBGLOG(DBG,"uprops: " << uprops);
00570     #endif
00571 
00572     EvalUnitModelBuildingProperties& mbprops = mbp[u];
00573     DBGLOG(DBG,"mbprops: " << printEUMBP(mbprops));
00574 
00575     // did we have an imodel upon function entry?
00576     bool hadIModel = !!mbprops.getIModel();
00577 
00578     // dummy handling for units without input
00579     if( !mbprops.needInput ) {
00580         DBGLOG(DBG,"unit needs no input");
00581         OptionalModel odummy;
00582         if( hadIModel ) {
00583             LOG(MODELB,"removing dummy model and failing");
00584             odummy = boost::none;
00585         }
00586         else {
00587             Model dummy;
00588             if( mg.modelsAt(u, MT_IN).empty() ) {
00589                 dummy = mg.addModel(u, MT_IN);
00590                 mg.propsOf(dummy).dummy = true;
00591                 LOG(MODELB,"setting new dummy model " << dummy);
00592             }
00593             else {
00594                 dummy = mg.modelsAt(u, MT_IN).front();
00595                 LOG(MODELB,"setting existing dummy model " << dummy);
00596                 assert(mg.propsOf(dummy).dummy);
00597             }
00598             odummy = dummy;
00599         }
00600         if( hadIModel && constantSpace )
00601             clearIModel(mbprops.getIModel().get());
00602         mbprops.setIModel(odummy);
00603         LOG(MODELB,"returning model " << printopt(odummy));
00604         #ifndef NDEBUG
00605         if( Logger::Instance().shallPrint(Logger::MODELB) && Logger::Instance().shallPrint(Logger::DBG) )
00606             printModelBuildingPropertyMap(std::cerr);
00607         #endif
00608         return odummy;
00609     }
00610 
00611     LOG(MODELB,"unit needs input");
00612 
00613     // prepare cursor handling
00614     typename EvalGraphT::PredecessorIterator pbegin, pend;
00615     typename EvalGraphT::PredecessorIterator cursor;
00616     boost::tie(pbegin, pend) = eg.getPredecessors(u);
00617 
00618     if( hadIModel ) {
00619         LOG(MODELB,"have imodel -> phase 1");
00620         boost::optional<EvalUnitPredecessorIterator> ncursor =
00621             ensureModelIncrement(u, pend - 1);
00622         if( !ncursor ) {
00623             LOG(MODELB,"got null cursor, returning no imodel");
00624             mbprops.setIModel(boost::none);
00625             #ifndef NDEBUG
00626             if( Logger::Instance().shallPrint(Logger::MODELB) && Logger::Instance().shallPrint(Logger::DBG) )
00627                 printModelBuildingPropertyMap(std::cerr);
00628             #endif
00629             return boost::none;
00630         }
00631         else {
00632             LOG(MODELB,"got some increment");
00633             cursor = ncursor.get();
00634         }
00635         // if( cursor == (pend - 1) )
00636         // "cursor++;" will increment it to pend
00637         // phase 2 loop will not be executed
00638         // model will be created and returned
00639         cursor++;
00640     }
00641     else {
00642         cursor = pbegin;
00643     }
00644 
00645     // now, cursor is index of first unit where we do not hold a refcount
00646     LOG(MODELB,"phase 2");
00647 
00648     while(cursor != pend) {
00649         typename EvalGraphT::EvalUnit ucursor =
00650             eg.targetOf(*cursor);
00651         EvalUnitModelBuildingProperties& ucursor_mbprops =
00652             mbp[ucursor];
00653         if( ucursor_mbprops.hasOModel() ) {
00654             LOG(MODELB,"predecessor " << ucursor <<
00655                 " has omodel " << mg.sourceOf(*ucursor_mbprops.currentisuccessor.get()) <<
00656                 " with refcount " << ucursor_mbprops.orefcount);
00657             ucursor_mbprops.orefcount++;
00658         }
00659         else {
00660             LOG(MODELB,"predecessor " << ucursor << " has no omodel");
00661             OptionalModel om = getNextOModel(ucursor);
00662             LOG(MODELB,"got next omodel " << printopt(om) << " at unit " << ucursor);
00663             if( !om ) {
00664                 if( cursor == pbegin ) {
00665                     LOG(MODELB,"backtracking impossible, returning no imodel");
00666                     mbprops.setIModel(boost::none);
00667                     #ifndef NDEBUG
00668                     if( Logger::Instance().shallPrint(Logger::MODELB) && Logger::Instance().shallPrint(Logger::DBG) )
00669                         printModelBuildingPropertyMap(std::cerr);
00670                     #endif
00671                     return boost::none;
00672                 }
00673                 else {
00674                     LOG(MODELB,"backtracking possible");
00675                     boost::optional<EvalUnitPredecessorIterator> ncursor =
00676                         ensureModelIncrement(u, cursor - 1);
00677                     if( !ncursor ) {
00678                         LOG(MODELB,"got null cursor, returning no imodel");
00679                         mbprops.setIModel(boost::none);
00680                         #ifndef NDEBUG
00681                         if( Logger::Instance().shallPrint(Logger::MODELB) && Logger::Instance().shallPrint(Logger::DBG) )
00682                             printModelBuildingPropertyMap(std::cerr);
00683                         #endif
00684                         return boost::none;
00685                     }
00686                     else {
00687                         LOG(MODELB,"backtracking was successful");
00688                         cursor = ncursor.get();
00689                     }
00690                 }
00691             }
00692         }
00693         cursor++;
00694     }                            // while(cursor != pend)
00695 
00696     LOG(MODELB,"found full input model, creating imodel!");
00697     Model im = createIModelFromPredecessorOModels(u);
00698     LOG(MODELB,"returning newly created imodel " << im);
00699     if( hadIModel && constantSpace )
00700         clearIModel(mbprops.getIModel().get());
00701     mbprops.setIModel(im);
00702     #ifndef NDEBUG
00703     if( Logger::Instance().shallPrint(Logger::MODELB) && Logger::Instance().shallPrint(Logger::DBG) )
00704         printModelBuildingPropertyMap(std::cerr);
00705     #endif
00706     return im;
00707 }
00708 
00709 
00710 // [checks if model generation is still possible given current input model]
00711 // [checks if no model is currently stored as current omodel]
00712 // if no model generator is running
00713 //   determines input interpretation
00714 //   start model generator
00715 // get next model from model generator
00716 // if successful
00717 //   create in model graph
00718 //   return model
00719 // else
00720 //   set finished for model generation
00721 //   return null
00722 template<typename EvalGraphT>
00723 typename OnlineModelBuilder<EvalGraphT>::OptionalModel
00724 OnlineModelBuilder<EvalGraphT>::createNextModel(
00725 EvalUnit u)
00726 {
00727     LOG_VSCOPE(MODELB,"cNM",u,true);
00728     DBGLOG(DBG,"=createNextModel(" << u << ")");
00729 
00730     EvalUnitModelBuildingProperties& mbprops = mbp[u];
00731 
00732     #ifndef NDEBUG
00733     // check if there can be a next model
00734     assert(!!mbprops.getIModel());
00735     assert(!mg.propsOf(mbprops.getIModel().get()).childModelsGenerated);
00736     assert(!mbprops.currentisuccessor);
00737     assert(mbprops.orefcount == 0);
00738     #endif
00739 
00740     if( !mbprops.currentmg ) {
00741         LOG(MODELB,"no model generator running");
00742 
00743         // determine input
00744         typename Interpretation::ConstPtr input;
00745         // input for creating model comes from current imodel
00746         // (this may be a dummy, so interpretation may be NULL which is ok)
00747         input = mg.propsOf(mbprops.getIModel().get()).interpretation;
00748 
00749         // mgf is of type ModelGeneratorFactory::Ptr
00750         LOG(MODELB,"creating model generator");
00751         mbprops.currentmg =
00752             eg.propsOf(u).mgf->createModelGenerator(input)
00753             ;
00754     }
00755 
00756     // use model generator to create new model
00757     DBGLOG(MODELB,"generating next model");
00758     assert(mbprops.currentmg);
00759     InterpretationPtr intp =
00760         mbprops.currentmg->generateNextModel();
00761 
00762     if( intp ) {
00763         // create model
00764         std::vector<Model> deps;
00765         deps.push_back(mbprops.getIModel().get());
00766         Model m = mg.addModel(u, MT_OUT, deps);
00767         // we got a new model
00768         LOG(MODELB,"stored new model " << m);
00769 
00770         // configure model
00771         mg.propsOf(m).interpretation = intp;
00772 
00773         // TODO: handle projection here?
00774         #ifndef NDEBUG
00775         const EvalUnitPropertyBundle& uprops = eg.propsOf(u);
00776         #endif
00777         assert(uprops.iproject == false);
00778         assert(uprops.oproject == false);
00779 
00780         LOG(MODELB,"setting currentisuccessor iterator");
00781         ModelSuccessorIterator sbegin, send;
00782         boost::tie(sbegin, send) = mg.getSuccessors(mbprops.getIModel().get());
00783         /*{
00784           for(ModelSuccessorIterator it = sbegin; it != send; ++it)
00785           {
00786             LOG("found successor " << mg.sourceOf(*it));
00787           }
00788         }*/
00789         ModelSuccessorIterator sit = send;
00790         sit--;
00791         assert(mg.sourceOf(*sit) == m);
00792         mbprops.currentisuccessor = sit;
00793 
00794         LOG(MODELB,"setting refcount to 1");
00795         mbprops.orefcount = 1;
00796         LOG(MODELB,"returning model " << m);
00797         return m;
00798     }
00799     else {
00800         // no further models for this model generator
00801         LOG(MODELB,"no further model");
00802 
00803         // learning over multiple units: push inconsistency reason of this unit into predecessory
00804         const Nogood* cause = mbprops.currentmg->getInconsistencyCause();
00805         if (cause){
00806             typename EvalGraphT::PredecessorIterator pit, pbegin, pend;
00807             boost::tie(pbegin, pend) = eg.getPredecessors(u);
00808             for (pit = pbegin; pit != pend; ++pit) {
00809                 eg.propsOf(eg.targetOf(*pit)).mgf->addInconsistencyCauseFromSuccessor(cause);
00810                 mbp[eg.targetOf(*pit)].currentmg->addNogood(cause);
00811             }
00812         }
00813 
00814         // mark this input model as finished for creating models
00815         ModelPropertyBundle& imodelprops = mg.propsOf(mbprops.getIModel().get());
00816         imodelprops.childModelsGenerated = true;
00817 
00818         // free model generator
00819         mbprops.currentmg.reset();
00820         LOG(MODELB,"returning no model");
00821         return boost::none;
00822     }
00823 }
00824 
00825 
00844 template<typename EvalGraphT>
00845 typename OnlineModelBuilder<EvalGraphT>::OptionalModel
00846 OnlineModelBuilder<EvalGraphT>::advanceOModelForIModel(
00847 EvalUnit u)
00848 {
00849     LOG_VSCOPE(MODELB,"aOMfIM",u,true);
00850     DBGLOG(DBG,"=OnlineModelBuilder<...>::advanceOModelForIModel(" << u << ")");
00851 
00852     // prepare
00853     EvalUnitModelBuildingProperties& mbprops = mbp[u];
00854     assert(mbprops.orefcount <= 1);
00855     assert(!!mbprops.getIModel());
00856 
00857     // get imodel + properties
00858                                  // Model == void* -> no ref!
00859     Model imodel = mbprops.getIModel().get();
00860     ModelPropertyBundle& imodelprops = mg.propsOf(imodel);
00861     LOG(MODELB,"have imodel " << imodel);
00862     DBGLOG(DBG,"imodel has properties " << print_method(imodelprops));
00863 
00864     // get successor list of imodel
00865     ModelSuccessorIterator sbegin, send;
00866     boost::tie(sbegin, send) = mg.getSuccessors(imodel);
00867     if( sbegin != send )
00868         LOG(MODELB,"imodel has at least one successor");
00869 
00870     LOG(MODELB,"trying to advance on model graph");
00871     if( !!mbprops.currentisuccessor ) {
00872         LOG(MODELB,"currentisuccessor is set");
00873         assert(mbprops.orefcount == 1);
00874 
00875         ModelSuccessorIterator& currentisuccessor = mbprops.currentisuccessor.get();
00876         assert(currentisuccessor != send);
00877         if( constantSpace )
00878             clearOModel(currentisuccessor);
00879         currentisuccessor++;
00880         if( currentisuccessor != send ) {
00881             Model m = mg.sourceOf(*currentisuccessor);
00882             LOG(MODELB,"advance successful, returning model " << m);
00883             return m;
00884         }
00885         else {
00886             LOG(MODELB,"resetting iterator");
00887             // reset iterator here because we cannot be sure that it can
00888             // point to a "current" model anymore, and we need to set it anew
00889             // anyways in case we create a new model below
00890             mbprops.currentisuccessor = boost::none;
00891             mbprops.orefcount = 0;
00892         }
00893     }
00894     else {
00895         LOG(MODELB,"currentisuccessor not set");
00896         assert(mbprops.orefcount == 0);
00897 
00898         if( sbegin != send ) {
00899             LOG(MODELB,"there are successors -> using them");
00900             mbprops.currentisuccessor = sbegin;
00901             mbprops.orefcount++;
00902             assert(mbprops.orefcount == 1);
00903             Model m = mg.sourceOf(*sbegin);
00904             LOG(MODELB,"returning first successor model " << m);
00905             return m;
00906         }
00907     }
00908 
00909     // here we know: we cannot advance on the model graph
00910     LOG(MODELB,"advancing on model graph failed");
00911     assert(!mbprops.currentisuccessor);
00912     assert(mbprops.orefcount == 0);
00913 
00914     if( imodelprops.childModelsGenerated ) {
00915         LOG(MODELB,"all successors created -> returning no model");
00916         return boost::none;
00917     }
00918 
00919     // here, not all models have been generated
00920     // -> create model generator if not existing
00921     // -> use model generator
00922 
00923     DBGLOG(MODELB,"attempting to create new model");
00924     OptionalModel m = createNextModel(u);
00925     LOG(MODELB,"returning model " << printopt(m));
00926     return m;
00927 }
00928 
00929 
00930 // get next output model (projected if projection is configured) at unit u
00931 template<typename EvalGraphT>
00932 typename OnlineModelBuilder<EvalGraphT>::OptionalModel
00933 OnlineModelBuilder<EvalGraphT>::getNextOModel(
00934 EvalUnit u)
00935 {
00936     LOG_VSCOPE(MODELB,"gnOM",u,true);
00937     DBGLOG(DBG,"=OnlineModelBuilder<...>::getNextOModel(" << u << "):");
00938 
00939     #ifndef NDEBUG
00940     const EvalUnitPropertyBundle& uprops = eg.propsOf(u);
00941     if( Logger::Instance().shallPrint(Logger::MODELB) && Logger::Instance().shallPrint(Logger::DBG) )
00942         printModelBuildingPropertyMap(std::cerr);
00943     DBGLOG(DBG,"uprops = " << uprops);
00944     #endif
00945 
00946     EvalUnitModelBuildingProperties& mbprops = mbp[u];
00947     DBGLOG(DBG,"mbprops = " << printEUMBP(mbprops));
00948 
00949     // are we allowed to go to the next model here?
00950     if( mbprops.orefcount > 1 ) {
00951         LOG(MODELB,"not allowed to continue because of orefcount > 1");
00952         // no -> give up our model refcount and return no model at all
00953         mbprops.orefcount--;
00954         #ifndef NDEBUG
00955         if( Logger::Instance().shallPrint(Logger::MODELB) && Logger::Instance().shallPrint(Logger::DBG) )
00956             printModelBuildingPropertyMap(std::cerr);
00957         #endif
00958         return OptionalModel();
00959     }
00960 
00961     // initialization?
00962     if( !mbprops.getIModel() ) {
00963         LOG(MODELB,"getting next imodel (none present and we need one)");
00964         assert(mbprops.orefcount == 0);
00965         // get next input for this unit (stores into mprops.imodel)
00966         getNextIModel(u);
00967         assert(!mbprops.currentisuccessor);
00968     }
00969 
00970     OptionalModel omodel;
00971     do {
00972         // fail if there is no input at this point
00973         if( !mbprops.getIModel() ) {
00974             LOG(MODELB,"failing with no input");
00975             assert(mbprops.orefcount == 0);
00976             #ifndef NDEBUG
00977             if( Logger::Instance().shallPrint(Logger::MODELB) && Logger::Instance().shallPrint(Logger::DBG) )
00978                 printModelBuildingPropertyMap(std::cerr);
00979             #endif
00980             return boost::none;
00981         }
00982 
00983         LOG(MODELB,"advancing omodel");
00984         // advance omodel, maybe advance to null model
00985         // advancing is only allowed if orefcount <= 1
00986         omodel = advanceOModelForIModel(u);
00987         if( !omodel ) {
00988             LOG(MODELB,"no omodel and have input models -> advancing imodel");
00989             // no next omodel found
00990             // -> advance imodel (stores into mbprops.imodel)
00991             getNextIModel(u);
00992         }
00993     }
00994     while( !omodel );
00995     assert(mbprops.orefcount == 1);
00996     LOG(MODELB,"returning omodel " << printopt(omodel));
00997     #ifndef NDEBUG
00998     if( Logger::Instance().shallPrint(Logger::MODELB) && Logger::Instance().shallPrint(Logger::DBG) )
00999         printModelBuildingPropertyMap(std::cerr);
01000     #endif
01001     return omodel;
01002 }
01003 
01004 
01005 DLVHEX_NAMESPACE_END
01006 #endif                           // ONLINE_MODEL_BUILDER_HPP_INCLUDED__23092010
01007 
01008 // vim:expandtab:ts=4:sw=4:
01009 // mode: C++
01010 // End: