|
dlvhex
2.1.0
|
00001 /* dlvhex -- Answer-Set Programming with external interfaces. 00002 * Copyright (C) 2005, 2006, 2007 Roman Schindlauer 00003 * Copyright (C) 2006, 2007, 2008, 2009, 2010 Thomas Krennwallner 00004 * Copyright (C) 2009, 2010 Peter Schüller 00005 * 00006 * This file is part of dlvhex. 00007 * 00008 * dlvhex is free software; you can redistribute it and/or modify it 00009 * under the terms of the GNU Lesser General Public License as 00010 * published by the Free Software Foundation; either version 2.1 of 00011 * the License, or (at your option) any later version. 00012 * 00013 * dlvhex is distributed in the hope that it will be useful, but 00014 * WITHOUT ANY WARRANTY; without even the implied warranty of 00015 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 00016 * Lesser General Public License for more details. 00017 * 00018 * You should have received a copy of the GNU Lesser General Public 00019 * License along with dlvhex; if not, write to the Free Software 00020 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 00021 * 02110-1301 USA. 00022 */ 00023 00031 #ifndef OFFLINE_MODEL_BUILDER_HPP_INCLUDED__28092010 00032 #define OFFLINE_MODEL_BUILDER_HPP_INCLUDED__28092010 00033 00034 #include "dlvhex2/PlatformDefinitions.h" 00035 #include "dlvhex2/OnlineModelBuilder.h" 00036 #include "dlvhex2/CAUAlgorithms.h" 00037 00038 DLVHEX_NAMESPACE_BEGIN 00039 00040 template<typename EvalGraphT> 00041 class OfflineModelBuilder: 00042 public OnlineModelBuilder<EvalGraphT> 00043 { 00044 // types 00045 protected: 00046 typedef OnlineModelBuilder<EvalGraphT> Base; 00047 00048 public: 00049 typedef OfflineModelBuilder<EvalGraphT> Self; 00050 00051 typedef typename Base::EvalUnit EvalUnit; 00052 typedef typename Base::EvalUnitDep EvalUnitDep; 00053 typedef typename Base::EvalUnitPropertyBundle EvalUnitPropertyBundle; 00054 typedef typename Base::MyModelGraph MyModelGraph; 00055 typedef typename Base::Model Model; 00056 typedef typename Base::ModelPropertyBundle ModelPropertyBundle; 00057 typedef typename Base::OptionalModel OptionalModel; 00058 typedef typename MyModelGraph::ModelList ModelList; 00059 typedef typename ModelList::const_iterator ModelListIterator; 00060 typedef boost::optional<ModelListIterator> OptionalModelListIterator; 00061 00062 protected: 00063 struct OfflineModelBuildingProperties 00064 { 00065 bool builtIModels; 00066 bool builtOModels; 00067 00068 // for non-joining iteration, we need this 00069 OptionalModelListIterator currentIModel; 00070 OptionalModelListIterator currentOModel; 00071 00072 OfflineModelBuildingProperties(): 00073 builtIModels(false), builtOModels(false), 00074 currentIModel(), currentOModel() {} 00075 }; 00076 typedef boost::vector_property_map<OfflineModelBuildingProperties> 00077 OfflineModelBuildingPropertyMap; 00078 00079 // storage 00080 protected: 00081 OfflineModelBuildingPropertyMap offmbp; 00082 // TODO: for each call we need this storage, this is not threadsafe! (but the rest of model building is unlikely to be threadsafe as well) 00083 boost::optional<CAUAlgorithms::JoinRelevancePropertyMap> currentjrp; 00084 00085 // methods 00086 public: 00087 OfflineModelBuilder(EvalGraphT& eg): 00088 Base(eg), offmbp() 00089 { 00090 // allocate full mbp (plus one unit, as we will likely get an additional vertex) 00091 OfflineModelBuildingProperties& offmbproptemp = offmbp[eg.countEvalUnits()]; 00092 (void)offmbproptemp; 00093 00094 // (defaults for properties are ok) 00095 } 00096 00097 virtual ~OfflineModelBuilder() { } 00098 00099 inline EvalGraphT& getEvalGraph() { return Base::getEvalGraph(); } 00100 inline MyModelGraph& getModelGraph() { return Base::getModelGraph(); } 00101 void printEvalGraphModelGraph(std::ostream& o) { Base::printEvalGraphModelGraph(o); } 00102 void printModelBuildingPropertyMap(std::ostream& o) { Base::printModelBuildingPropertyMap(o); } 00103 00104 virtual unsigned buildIModels(EvalUnit u); 00105 virtual unsigned buildOModels(EvalUnit u); 00106 00107 // automatically calls buildOModelsRecursively on any non-calculated predecessor 00108 virtual unsigned buildIModelsRecursively(EvalUnit u); 00109 // automatically calls buildIModelsRecursively if imodels are not calculated yet 00110 virtual unsigned buildOModelsRecursively(EvalUnit u); 00111 00112 protected: 00113 // get next input model (projected if projection is configured) at unit u 00114 virtual OptionalModel getNextIModel(EvalUnit u); 00115 }; 00116 00117 template<typename EvalGraphT> 00118 unsigned OfflineModelBuilder<EvalGraphT>::buildIModels( 00119 typename OfflineModelBuilder<EvalGraphT>::EvalUnit u) 00120 { 00121 LOG_VSCOPE(MODELB,"bIM",u,true); 00122 DBGLOG(DBG,"=OfflineModelBuilder<...>::buildIModels(" << u << ")"); 00123 //const EvalUnitPropertyBundle& uprops = Base::eg.propsOf(u); 00124 //LOG("rules: " << uprops.ctx.rules); 00125 00126 typename EvalGraphT::PredecessorIterator pbegin, pend; 00127 boost::tie(pbegin, pend) = Base::eg.getPredecessors(u); 00128 00129 #ifndef NDEBUG 00130 typename EvalGraphT::PredecessorIterator pit; 00131 for(pit = pbegin; pit != pend; ++pit) 00132 { 00133 EvalUnit upred = Base::eg.targetOf(*pit); 00134 assert(offmbp[upred].builtOModels == true); 00135 } 00136 #endif 00137 00138 assert(offmbp[u].builtIModels == false); 00139 00140 // if no predecessors 00141 // call Base::getNextIModel while it returns (dummy) models 00142 // if 1 predecessor 00143 // call Self::getNextIModel with limit where nothing is relevant 00144 // (this returns (simply linked) models without backtracking in the model graph) 00145 // otherwise 00146 // calculate CAUs from u 00147 // calculate join-relevant units 00148 // call Self::getNextIModel while it returns models 00149 // mark u as calculated 00150 // return number of generated models 00151 00152 unsigned modelcounter = 0; 00153 if( pbegin == pend ) 00154 { 00155 // no predecessors -> create dummy models using base class functionality 00156 LOG(MODELB,"asking for (dummy) models"); 00157 while(Base::getNextIModel(u) != boost::none) 00158 modelcounter++; 00159 } 00160 else if( (pbegin+1) == pend ) 00161 { 00162 // one predecessor -> create jrp directly (no CAUAlgorithms required, although they would do the job) 00163 LOG(MODELB,"one predecessor, manually creating join relevance"); 00164 assert(!currentjrp); 00165 00166 CAUAlgorithms::JoinRelevancePropertyMap jr; 00167 CAUAlgorithms::initJoinRelevance(jr, Base::eg); 00168 currentjrp = jr; 00169 00170 DBGLOG(DBG,"asking for imodels"); 00171 while(Base::getNextIModel(u) != boost::none) 00172 modelcounter++; 00173 LOG(MODELB,"created " << modelcounter << " imodels"); 00174 00175 currentjrp = boost::none; 00176 } 00177 else 00178 { 00179 LOG(MODELB,"more than one predecessor -> using CAUAlgorithms"); 00180 assert(!currentjrp); 00181 00182 CAUAlgorithms::AncestryPropertyMap apm; 00183 std::set<EvalUnit> caus; 00184 CAUAlgorithms::findCAUs(caus, Base::eg, u, apm); 00185 CAUAlgorithms::logAPM(apm); 00186 CAUAlgorithms::JoinRelevancePropertyMap jr; 00187 CAUAlgorithms::markJoinRelevance(jr, Base::eg, u, caus, apm); 00188 CAUAlgorithms::logJRPM(jr); 00189 currentjrp = jr; 00190 00191 DBGLOG(DBG,"asking for imodels"); 00192 while(Base::getNextIModel(u) != boost::none) 00193 modelcounter++; 00194 LOG(MODELB,"created " << modelcounter << " imodels"); 00195 00196 currentjrp = boost::none; 00197 } 00198 00199 offmbp[u].builtIModels = true; 00200 return modelcounter; 00201 } 00202 00203 template<typename EvalGraphT> 00204 unsigned OfflineModelBuilder<EvalGraphT>::buildOModels( 00205 EvalUnit u) 00206 { 00207 LOG_VSCOPE(MODELB,"bOM",u,true); 00208 DBGLOG(DBG,"=OfflineModelBuilder<...>::buildOModels(" << u << ")"); 00209 //const EvalUnitPropertyBundle& uprops = Base::eg.propsOf(u); 00210 //LOG("rules: " << uprops.ctx.rules); 00211 00212 assert(offmbp[u].builtIModels == true); 00213 assert(offmbp[u].builtOModels == false); 00214 00215 // for all imodels present 00216 // call Base::getNextOModel while it returns models 00217 // mark u as calculated 00218 // return number of generated models 00219 00220 unsigned modelcounter = 0; 00221 00222 assert(!currentjrp); 00223 CAUAlgorithms::JoinRelevancePropertyMap jr; 00224 CAUAlgorithms::initJoinRelevance(jr, Base::eg); 00225 currentjrp = jr; 00226 00227 DBGLOG(DBG,"asking for omodels"); 00228 while(Base::getNextOModel(u) != boost::none) 00229 modelcounter++; 00230 LOG(MODELB,"created " << modelcounter << " omodels"); 00231 00232 currentjrp = boost::none; 00233 offmbp[u].builtOModels = true; 00234 return modelcounter; 00235 } 00236 00237 // automatically calls buildOModelsRecursively on any non-calculated predecessor 00238 template<typename EvalGraphT> 00239 unsigned OfflineModelBuilder<EvalGraphT>::buildIModelsRecursively( 00240 EvalUnit u) 00241 { 00242 LOG_VSCOPE(MODELB,"bIMR",u,true); 00243 DBGLOG(DBG,"=OfflineModelBuilder<...>::buildIModelsRecursively(" << u << ")@" << printptr(this)); 00244 00245 // no assertions here, we succeed if we already built the models 00246 if( offmbp[u].builtIModels == true ) 00247 { 00248 unsigned count = Base::mg.modelsAt(u,MT_IN).size(); // TODO: how about iproject? 00249 LOG(MODELB,"already built -> counting " << count << " imodels"); 00250 return count; 00251 } 00252 00253 typename EvalGraphT::PredecessorIterator pbegin, pend; 00254 boost::tie(pbegin, pend) = Base::eg.getPredecessors(u); 00255 00256 typename EvalGraphT::PredecessorIterator pit; 00257 for(pit = pbegin; pit != pend; ++pit) 00258 { 00259 EvalUnit upred = Base::eg.targetOf(*pit); 00260 if( offmbp[upred].builtOModels == false ) 00261 { 00262 LOG(MODELB,"predecessor " << upred << " has no built omodels"); 00263 unsigned count = buildOModelsRecursively(upred); 00264 LOG(MODELB,"built " << count << " models in predecessor"); 00265 } 00266 else 00267 { 00268 LOG(MODELB,"predecessor " << upred << " has omodels"); 00269 } 00270 } 00271 00272 unsigned count = buildIModels(u); 00273 LOG(MODELB,"built " << count << " imodels here"); 00274 return count; 00275 } 00276 00277 template<typename EvalGraphT> 00278 // automatically calls buildIModelsRecursively if imodels are not calculated yet 00279 unsigned OfflineModelBuilder<EvalGraphT>::buildOModelsRecursively( 00280 EvalUnit u) 00281 { 00282 LOG_VSCOPE(MODELB,"bOMR",u,true); 00283 DBGLOG(DBG,"=OfflineModelBuilder<...>::buildOModelsRecursively(" << u << ")@" << printptr(this)); 00284 00285 // no assertions here, we succeed if we already built the models 00286 if( offmbp[u].builtOModels == true ) 00287 { 00288 unsigned count = Base::mg.modelsAt(u,MT_OUT).size(); // TODO: how about oproject? 00289 LOG(MODELB,"already built -> counting " << count << " omodels"); 00290 return count; 00291 } 00292 00293 if( offmbp[u].builtIModels == false ) 00294 { 00295 LOG(MODELB,"have no imodels"); 00296 unsigned count = buildIModelsRecursively(u); 00297 LOG(MODELB,"built " << count << " imodels here"); 00298 } 00299 else 00300 { 00301 LOG(MODELB,"already have imodels"); 00302 } 00303 00304 unsigned count = buildOModels(u); 00305 LOG(MODELB,"built " << count << " omodels here"); 00306 return count; 00307 } 00308 00309 template<typename EvalGraphT> 00310 typename OfflineModelBuilder<EvalGraphT>::OptionalModel 00311 OfflineModelBuilder<EvalGraphT>::getNextIModel( 00312 EvalUnit u) 00313 { 00314 LOG_VSCOPE(MODELB,"offgnIM",u,true); 00315 DBGLOG(DBG,"=OfflineModelBuilder<...>::getNextIModel(" << u << ")"); 00316 //logEvalGraphModelGraph(); 00317 00318 assert(!!currentjrp); 00319 if( currentjrp.get()[u] ) 00320 { 00321 LOG(MODELB,"join relevant"); 00322 return Base::getNextIModel(u); 00323 } 00324 else 00325 { 00326 LOG(MODELB,"not join relevant"); 00327 assert(offmbp[u].builtIModels); 00328 // TODO how about iproj? 00329 const ModelList& mlist = Base::mg.modelsAt(u, MT_IN); 00330 if( !!offmbp[u].currentIModel ) 00331 { 00332 //assert(offmbp[u].currentIModel.get() != mlist.end()); 00333 LOG(MODELB,"advancing iterator"); 00334 //if( Base::mg.propsOf(*offmbp[u].currentIModel.get()).dummy == 1 ) 00335 // logEvalGraphModelGraph(); 00336 offmbp[u].currentIModel.get()++; 00337 } 00338 else 00339 { 00340 LOG(MODELB,"initializing iterator"); 00341 offmbp[u].currentIModel = mlist.begin(); 00342 } 00343 if( offmbp[u].currentIModel.get() == mlist.end() ) 00344 { 00345 LOG(MODELB,"no more models"); 00346 Base::mbp[u].setIModel(boost::none); 00347 offmbp[u].currentIModel = boost::none; 00348 return boost::none; 00349 } 00350 else 00351 { 00352 Model m = *offmbp[u].currentIModel.get(); 00353 Base::mbp[u].setIModel(m); 00354 LOG(MODELB,"got model " << m); 00355 return m; 00356 } 00357 } 00358 } 00359 00360 DLVHEX_NAMESPACE_END 00361 00362 #endif // OFFLINE_MODEL_BUILDER_HPP_INCLUDED__28092010