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 #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: