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 OFFLINE_MODEL_BUILDER_HPP_INCLUDED__28092010 00035 #define OFFLINE_MODEL_BUILDER_HPP_INCLUDED__28092010 00036 00037 #include "dlvhex2/PlatformDefinitions.h" 00038 #include "dlvhex2/OnlineModelBuilder.h" 00039 #include "dlvhex2/CAUAlgorithms.h" 00040 00041 DLVHEX_NAMESPACE_BEGIN 00042 00044 template<typename EvalGraphT> 00045 class OfflineModelBuilder: 00046 public OnlineModelBuilder<EvalGraphT> 00047 { 00048 // types 00049 protected: 00050 typedef OnlineModelBuilder<EvalGraphT> Base; 00051 00052 public: 00053 typedef OfflineModelBuilder<EvalGraphT> Self; 00054 00055 typedef typename Base::EvalUnit EvalUnit; 00056 typedef typename Base::EvalUnitDep EvalUnitDep; 00057 typedef typename Base::EvalUnitPropertyBundle EvalUnitPropertyBundle; 00058 typedef typename Base::MyModelGraph MyModelGraph; 00059 typedef typename Base::Model Model; 00060 typedef typename Base::ModelPropertyBundle ModelPropertyBundle; 00061 typedef typename Base::OptionalModel OptionalModel; 00062 typedef typename MyModelGraph::ModelList ModelList; 00063 typedef typename ModelList::const_iterator ModelListIterator; 00064 typedef boost::optional<ModelListIterator> OptionalModelListIterator; 00065 00066 protected: 00068 struct OfflineModelBuildingProperties 00069 { 00071 bool builtIModels; 00073 bool builtOModels; 00074 00075 // for non-joining iteration, we need this 00077 OptionalModelListIterator currentIModel; 00079 OptionalModelListIterator currentOModel; 00080 00082 OfflineModelBuildingProperties(): 00083 builtIModels(false), builtOModels(false), 00084 currentIModel(), currentOModel() {} 00085 }; 00086 typedef boost::vector_property_map<OfflineModelBuildingProperties> 00087 OfflineModelBuildingPropertyMap; 00088 00089 // storage 00090 protected: 00092 OfflineModelBuildingPropertyMap offmbp; 00094 boost::optional<CAUAlgorithms::JoinRelevancePropertyMap> currentjrp; 00095 00096 // methods 00097 public: 00100 OfflineModelBuilder(ModelBuilderConfig<EvalGraphT>& cfg): 00101 Base(cfg), offmbp() { 00102 // allocate full mbp (plus one unit, as we will likely get an additional vertex) 00103 EvalGraphT& eg = cfg.eg; 00104 OfflineModelBuildingProperties& offmbproptemp = offmbp[eg.countEvalUnits()]; 00105 (void)offmbproptemp; 00106 00107 // (defaults for properties are ok) 00108 } 00110 virtual ~OfflineModelBuilder() { } 00111 00112 inline EvalGraphT& getEvalGraph() { return Base::getEvalGraph(); } 00113 inline MyModelGraph& getModelGraph() { return Base::getModelGraph(); } 00114 void printEvalGraphModelGraph(std::ostream& o) { Base::printEvalGraphModelGraph(o); } 00115 void printModelBuildingPropertyMap(std::ostream& o) { Base::printModelBuildingPropertyMap(o); } 00116 00119 virtual unsigned buildIModels(EvalUnit u); 00122 virtual unsigned buildOModels(EvalUnit u); 00123 00124 // automatically calls buildOModelsRecursively on any non-calculated predecessor 00125 virtual unsigned buildIModelsRecursively(EvalUnit u); 00126 // automatically calls buildIModelsRecursively if imodels are not calculated yet 00127 virtual unsigned buildOModelsRecursively(EvalUnit u); 00128 00129 protected: 00130 // get next input model (projected if projection is configured) at unit u 00131 virtual OptionalModel getNextIModel(EvalUnit u); 00132 }; 00133 00134 template<typename EvalGraphT> 00135 unsigned OfflineModelBuilder<EvalGraphT>::buildIModels( 00136 typename OfflineModelBuilder<EvalGraphT>::EvalUnit u) 00137 { 00138 LOG_VSCOPE(MODELB,"bIM",u,true); 00139 DBGLOG(DBG,"=OfflineModelBuilder<...>::buildIModels(" << u << ")"); 00140 //const EvalUnitPropertyBundle& uprops = Base::eg.propsOf(u); 00141 //LOG("rules: " << uprops.ctx.rules); 00142 00143 typename EvalGraphT::PredecessorIterator pbegin, pend; 00144 boost::tie(pbegin, pend) = Base::eg.getPredecessors(u); 00145 00146 #ifndef NDEBUG 00147 typename EvalGraphT::PredecessorIterator pit; 00148 for(pit = pbegin; pit != pend; ++pit) { 00149 EvalUnit upred = Base::eg.targetOf(*pit); 00150 assert(offmbp[upred].builtOModels == true); 00151 } 00152 #endif 00153 00154 assert(offmbp[u].builtIModels == false); 00155 00156 // if no predecessors 00157 // call Base::getNextIModel while it returns (dummy) models 00158 // if 1 predecessor 00159 // call Self::getNextIModel with limit where nothing is relevant 00160 // (this returns (simply linked) models without backtracking in the model graph) 00161 // otherwise 00162 // calculate CAUs from u 00163 // calculate join-relevant units 00164 // call Self::getNextIModel while it returns models 00165 // mark u as calculated 00166 // return number of generated models 00167 00168 unsigned modelcounter = 0; 00169 if( pbegin == pend ) { 00170 // no predecessors -> create dummy models using base class functionality 00171 LOG(MODELB,"asking for (dummy) models"); 00172 while(Base::getNextIModel(u) != boost::none) 00173 modelcounter++; 00174 } 00175 else if( (pbegin+1) == pend ) { 00176 // one predecessor -> create jrp directly (no CAUAlgorithms required, although they would do the job) 00177 LOG(MODELB,"one predecessor, manually creating join relevance"); 00178 assert(!currentjrp); 00179 00180 CAUAlgorithms::JoinRelevancePropertyMap jr; 00181 CAUAlgorithms::initJoinRelevance(jr, Base::eg); 00182 currentjrp = jr; 00183 00184 DBGLOG(DBG,"asking for imodels"); 00185 while(Base::getNextIModel(u) != boost::none) 00186 modelcounter++; 00187 LOG(MODELB,"created " << modelcounter << " imodels"); 00188 00189 currentjrp = boost::none; 00190 } 00191 else { 00192 LOG(MODELB,"more than one predecessor -> using CAUAlgorithms"); 00193 assert(!currentjrp); 00194 00195 CAUAlgorithms::AncestryPropertyMap apm; 00196 std::set<EvalUnit> caus; 00197 CAUAlgorithms::findCAUs(caus, Base::eg, u, apm); 00198 CAUAlgorithms::logAPM(apm); 00199 CAUAlgorithms::JoinRelevancePropertyMap jr; 00200 CAUAlgorithms::markJoinRelevance(jr, Base::eg, u, caus, apm); 00201 CAUAlgorithms::logJRPM(jr); 00202 currentjrp = jr; 00203 00204 DBGLOG(DBG,"asking for imodels"); 00205 while(Base::getNextIModel(u) != boost::none) 00206 modelcounter++; 00207 LOG(MODELB,"created " << modelcounter << " imodels"); 00208 00209 currentjrp = boost::none; 00210 } 00211 00212 offmbp[u].builtIModels = true; 00213 return modelcounter; 00214 } 00215 00216 00217 template<typename EvalGraphT> 00218 unsigned OfflineModelBuilder<EvalGraphT>::buildOModels( 00219 EvalUnit u) 00220 { 00221 LOG_VSCOPE(MODELB,"bOM",u,true); 00222 DBGLOG(DBG,"=OfflineModelBuilder<...>::buildOModels(" << u << ")"); 00223 //const EvalUnitPropertyBundle& uprops = Base::eg.propsOf(u); 00224 //LOG("rules: " << uprops.ctx.rules); 00225 00226 assert(offmbp[u].builtIModels == true); 00227 assert(offmbp[u].builtOModels == false); 00228 00229 // for all imodels present 00230 // call Base::getNextOModel while it returns models 00231 // mark u as calculated 00232 // return number of generated models 00233 00234 unsigned modelcounter = 0; 00235 00236 assert(!currentjrp); 00237 CAUAlgorithms::JoinRelevancePropertyMap jr; 00238 CAUAlgorithms::initJoinRelevance(jr, Base::eg); 00239 currentjrp = jr; 00240 00241 DBGLOG(DBG,"asking for omodels"); 00242 while(Base::getNextOModel(u) != boost::none) 00243 modelcounter++; 00244 LOG(MODELB,"created " << modelcounter << " omodels"); 00245 00246 currentjrp = boost::none; 00247 offmbp[u].builtOModels = true; 00248 return modelcounter; 00249 } 00250 00251 00252 // automatically calls buildOModelsRecursively on any non-calculated predecessor 00253 template<typename EvalGraphT> 00254 unsigned OfflineModelBuilder<EvalGraphT>::buildIModelsRecursively( 00255 EvalUnit u) 00256 { 00257 LOG_VSCOPE(MODELB,"bIMR",u,true); 00258 DBGLOG(DBG,"=OfflineModelBuilder<...>::buildIModelsRecursively(" << u << ")@" << printptr(this)); 00259 00260 // no assertions here, we succeed if we already built the models 00261 if( offmbp[u].builtIModels == true ) { 00262 // TODO: how about iproject? 00263 unsigned count = Base::mg.modelsAt(u,MT_IN).size(); 00264 LOG(MODELB,"already built -> counting " << count << " imodels"); 00265 return count; 00266 } 00267 00268 typename EvalGraphT::PredecessorIterator pbegin, pend; 00269 boost::tie(pbegin, pend) = Base::eg.getPredecessors(u); 00270 00271 typename EvalGraphT::PredecessorIterator pit; 00272 for(pit = pbegin; pit != pend; ++pit) { 00273 EvalUnit upred = Base::eg.targetOf(*pit); 00274 if( offmbp[upred].builtOModels == false ) { 00275 LOG(MODELB,"predecessor " << upred << " has no built omodels"); 00276 unsigned count = buildOModelsRecursively(upred); 00277 LOG(MODELB,"built " << count << " models in predecessor"); 00278 } 00279 else { 00280 LOG(MODELB,"predecessor " << upred << " has omodels"); 00281 } 00282 } 00283 00284 unsigned count = buildIModels(u); 00285 LOG(MODELB,"built " << count << " imodels here"); 00286 return count; 00287 } 00288 00289 00290 template<typename EvalGraphT> 00291 // automatically calls buildIModelsRecursively if imodels are not calculated yet 00292 unsigned OfflineModelBuilder<EvalGraphT>::buildOModelsRecursively( 00293 EvalUnit u) 00294 { 00295 LOG_VSCOPE(MODELB,"bOMR",u,true); 00296 DBGLOG(DBG,"=OfflineModelBuilder<...>::buildOModelsRecursively(" << u << ")@" << printptr(this)); 00297 00298 // no assertions here, we succeed if we already built the models 00299 if( offmbp[u].builtOModels == true ) { 00300 // TODO: how about oproject? 00301 unsigned count = Base::mg.modelsAt(u,MT_OUT).size(); 00302 LOG(MODELB,"already built -> counting " << count << " omodels"); 00303 return count; 00304 } 00305 00306 if( offmbp[u].builtIModels == false ) { 00307 LOG(MODELB,"have no imodels"); 00308 unsigned count = buildIModelsRecursively(u); 00309 LOG(MODELB,"built " << count << " imodels here"); 00310 } 00311 else { 00312 LOG(MODELB,"already have imodels"); 00313 } 00314 00315 unsigned count = buildOModels(u); 00316 LOG(MODELB,"built " << count << " omodels here"); 00317 return count; 00318 } 00319 00320 00321 template<typename EvalGraphT> 00322 typename OfflineModelBuilder<EvalGraphT>::OptionalModel 00323 OfflineModelBuilder<EvalGraphT>::getNextIModel( 00324 EvalUnit u) 00325 { 00326 LOG_VSCOPE(MODELB,"offgnIM",u,true); 00327 DBGLOG(DBG,"=OfflineModelBuilder<...>::getNextIModel(" << u << ")"); 00328 //logEvalGraphModelGraph(); 00329 00330 assert(!!currentjrp); 00331 if( currentjrp.get()[u] ) { 00332 LOG(MODELB,"join relevant"); 00333 return Base::getNextIModel(u); 00334 } 00335 else { 00336 LOG(MODELB,"not join relevant"); 00337 assert(offmbp[u].builtIModels); 00338 // TODO how about iproj? 00339 const ModelList& mlist = Base::mg.modelsAt(u, MT_IN); 00340 if( !!offmbp[u].currentIModel ) { 00341 //assert(offmbp[u].currentIModel.get() != mlist.end()); 00342 LOG(MODELB,"advancing iterator"); 00343 //if( Base::mg.propsOf(*offmbp[u].currentIModel.get()).dummy == 1 ) 00344 // logEvalGraphModelGraph(); 00345 offmbp[u].currentIModel.get()++; 00346 } 00347 else { 00348 LOG(MODELB,"initializing iterator"); 00349 offmbp[u].currentIModel = mlist.begin(); 00350 } 00351 if( offmbp[u].currentIModel.get() == mlist.end() ) { 00352 LOG(MODELB,"no more models"); 00353 Base::mbp[u].setIModel(boost::none); 00354 offmbp[u].currentIModel = boost::none; 00355 return boost::none; 00356 } 00357 else { 00358 Model m = *offmbp[u].currentIModel.get(); 00359 Base::mbp[u].setIModel(m); 00360 LOG(MODELB,"got model " << m); 00361 return m; 00362 } 00363 } 00364 } 00365 00366 00367 DLVHEX_NAMESPACE_END 00368 #endif // OFFLINE_MODEL_BUILDER_HPP_INCLUDED__28092010 00369 00370 // vim:expandtab:ts=4:sw=4: 00371 // mode: C++ 00372 // End: