dlvhex
2.5.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 #ifdef HAVE_CONFIG_H 00032 #include "config.h" 00033 #endif // HAVE_CONFIG_H 00034 00035 // dlvhex 00036 #define DLVHEX_BENCHMARK 00037 00038 #include "dlvhex2/HexParser.h" 00039 #include "dlvhex2/PlatformDefinitions.h" 00040 #include "dlvhex2/Logger.h" 00041 #include "dlvhex2/ID.h" 00042 #include "dlvhex2/Table.h" 00043 #include "dlvhex2/TermTable.h" 00044 #include "dlvhex2/OrdinaryAtomTable.h" 00045 #include "dlvhex2/BuiltinAtomTable.h" 00046 #include "dlvhex2/AggregateAtomTable.h" 00047 #include "dlvhex2/ExternalAtomTable.h" 00048 #include "dlvhex2/RuleTable.h" 00049 #include "dlvhex2/ASPSolverManager.h" 00050 #include "dlvhex2/ASPSolver.h" 00051 #include "dlvhex2/Registry.h" 00052 #include "dlvhex2/Printer.h" 00053 #include "dlvhex2/ProgramCtx.h" 00054 #include "dlvhex2/PluginInterface.h" 00055 #include "dlvhex2/EvalGraphBuilder.h" 00056 #include "dlvhex2/EvalHeuristicOldDlvhex.h" 00057 #include "dlvhex2/EvalHeuristicTrivial.h" 00058 #include "dlvhex2/EvalHeuristicEasy.h" 00059 #include "dlvhex2/InputProvider.h" 00060 #include "dlvhex2/DependencyGraph.h" 00061 #include "dlvhex2/ComponentGraph.h" 00062 #include "dlvhex2/ModelGenerator.h" 00063 #include "dlvhex2/Benchmarking.h" 00064 #include "dlvhex2/OnlineModelBuilder.h" 00065 #include "dlvhex2/OfflineModelBuilder.h" 00066 00067 // other 00068 00069 #include <boost/algorithm/string/replace.hpp> 00070 #include <boost/bind.hpp> 00071 #include <boost/ref.hpp> 00072 #include <iostream> 00073 #include <fstream> 00074 #include <cstdlib> 00075 00076 #include "graphviz.h" 00077 00078 LOG_INIT(Logger::ERROR | Logger::WARNING) 00079 00080 #ifndef NDEBUG 00081 # define LOG_REGISTRY_PROGRAM(ctx) \ 00082 DBGLOG(DBG,*ctx.registry()); \ 00083 RawPrinter printer(std::cerr, ctx.registry()); \ 00084 std::cerr << "edb = " << *ctx.edb << std::endl; \ 00085 DBGLOG(DBG,"idb"); \ 00086 printer.printmany(ctx.idb,"\n"); \ 00087 std::cerr << std::endl; \ 00088 DBGLOG(DBG,"idb end"); 00089 #else 00090 # define LOG_REGISTRY_PROGRAM(ctx) \ 00091 do {} while(false); 00092 #endif 00093 00094 using dlvhex::MT_IN; 00095 using dlvhex::MT_OUT; 00096 00097 typedef boost::function<void (std::ostream&)> GraphVizFunc; 00098 00099 inline void writeGraphVizFunctors(GraphVizFunc vfunc, GraphVizFunc tfunc, const std::string& fnamestart) 00100 { 00101 std::string fnamev(fnamestart); 00102 fnamev += "Verbose.dot"; 00103 LOG(INFO,"dumping verbose graph to " << fnamev); 00104 std::ofstream filev(fnamev.c_str()); 00105 vfunc(filev); 00106 makeGraphVizPdf(fnamev.c_str()); 00107 00108 std::string fnamet(fnamestart); 00109 fnamet += "Terse.dot"; 00110 LOG(INFO,"dumping terse graph to " << fnamet); 00111 std::ofstream filet(fnamet.c_str()); 00112 tfunc(filet); 00113 makeGraphVizPdf(fnamet.c_str()); 00114 } 00115 00116 template<typename GraphVizzyT> 00117 inline void writeGraphViz(const GraphVizzyT& gv, const std::string& fnamestart) 00118 { 00119 GraphVizFunc vfunc = boost::bind(&GraphVizzyT::writeGraphViz, boost::cref(gv), _1, true); 00120 GraphVizFunc tfunc = boost::bind(&GraphVizzyT::writeGraphViz, boost::cref(gv), _1, false); 00121 writeGraphVizFunctors(vfunc, tfunc, fnamestart); 00122 } 00123 00124 DLVHEX_NAMESPACE_USE 00125 00126 void breakLinesAndGraphViz(const std::string& str, std::ostream& o) 00127 { 00128 unsigned at = 0; 00129 for(std::string::const_iterator it = str.begin(); it != str.end(); ++it) 00130 { 00131 char c = *it; 00132 if( c == '\\' ) // assume this is a newline 00133 at = 0; 00134 if( c == '\"' ) 00135 o << "\\\""; 00136 else 00137 o << c; 00138 // make a new line at least all 25 characters if there is a ',' 00139 at++; 00140 if( at > 25 && c == ',' ) 00141 { 00142 at = 0; 00143 o << "\\n"; 00144 } 00145 } 00146 } 00147 00148 typedef FinalEvalGraph::EvalUnit EvalUnit; 00149 00150 // 00151 // model graph printing: putting this into ModelGraph is insane (modelgraph has a too abstract view of the model) 00152 // TODO think about improving the above situation 00153 // 00154 00155 /* graphviz schema: 00156 digraph G { 00157 compound=true; 00158 subgraph evalunit1 { 00159 model1 [label1]; 00160 } 00161 subgraph cluster1 { 00162 ... 00163 } 00164 ... 00165 model1 -> model2; 00166 ... 00167 } 00168 */ 00169 // output graph as graphviz source 00170 template<typename ModelGraphT> 00171 void writeEgMgGraphViz( 00172 std::ostream& o, bool verbose, 00173 const FinalEvalGraph& eg, const ModelGraphT& mg, 00174 boost::optional<std::set<typename ModelGraphT::Model> > onlyForModels = boost::none) 00175 { 00176 typedef typename ModelGraphT::ModelList ModelList; 00177 typedef typename ModelGraphT::Model Model; 00178 typedef typename ModelGraphT::PredecessorIterator ModelPredecessorIterator; 00179 typedef typename ModelGraphT::ModelIterator ModelIterator; 00180 typedef std::set<typename ModelGraphT::Model> ModelSet; 00181 00182 ModelSet printModels; 00183 if( !!onlyForModels ) 00184 { 00185 // we need a hash map, as component graph is no graph with vecS-storage 00186 typedef boost::unordered_map<Model, boost::default_color_type> ColorHashMap; 00187 typedef boost::associative_property_map<ColorHashMap> ColorMap; 00188 ColorHashMap whiteHashMap; 00189 00190 // fill white hash map 00191 ModelIterator mit, mit_end; 00192 for(boost::tie(mit, mit_end) = mg.getModels(); 00193 mit != mit_end; ++mit) 00194 { 00195 whiteHashMap[*mit] = boost::white_color; 00196 } 00197 00198 // one hash map for all! 00199 ColorHashMap myHashMap(whiteHashMap); 00200 ColorMap myColorMap(myHashMap); 00201 for(typename ModelSet::const_iterator it = onlyForModels.get().begin(); 00202 it != onlyForModels.get().end(); ++it) 00203 { 00204 //LOG(INFO,"doing dfs visit for " << *it); 00205 boost::depth_first_visit( 00206 mg.getInternalGraph(), 00207 *it, 00208 boost::default_dfs_visitor(), 00209 myColorMap); 00210 } 00211 for(boost::tie(mit, mit_end) = mg.getModels(); 00212 mit != mit_end; ++mit) 00213 { 00214 if( myHashMap[*mit] == boost::white_color ) 00215 { 00216 //LOG(INFO,"model " << *mit << " still white"); 00217 } 00218 else 00219 { 00220 //LOG(INFO,"model " << *mit << " not white -> printing"); 00221 printModels.insert(*mit); 00222 } 00223 } 00224 } 00225 else 00226 { 00227 // include all 00228 ModelIterator mit, mit_end; 00229 for(boost::tie(mit, mit_end) = mg.getModels(); 00230 mit != mit_end; ++mit) 00231 { 00232 printModels.insert(*mit); 00233 } 00234 } 00235 00236 // boost::graph::graphviz is horribly broken! 00237 // therefore we print it ourselves 00238 00239 o << "digraph G {" << std::endl << 00240 "rankdir=BT;" << std::endl << // print root nodes at bottom, leaves at top! 00241 "concentrate=true;" << std::endl << 00242 //"center=false;" << std::endl << 00243 "pagedir=BL;" << std::endl << 00244 //"ranksep=\"0.5\";" << std::endl << 00245 //"nodesep=\"0.5\";" << std::endl << 00246 //"page=\"44,35\";" << std::endl << 00247 "compound=true;" << std::endl; // print clusters = eval units, inside nodes = models 00248 00249 // stream deps into this stream 00250 std::stringstream odeps; 00251 00252 FinalEvalGraph::EvalUnitIterator uit, ubegin, uend; 00253 boost::tie(ubegin, uend) = eg.getEvalUnits(); 00254 for(uit = ubegin; uit != uend; ++uit) 00255 { 00256 EvalUnit u = *uit; 00257 o << "subgraph clusteru" << u << "{" << std::endl; 00258 o << "node [shape=box];" << std::endl; 00259 o << "label=\""; 00260 { 00261 std::stringstream s; 00262 if( eg.propsOf(u).mgf != 0 ) 00263 { 00264 s << *eg.propsOf(u).mgf; 00265 } 00266 else 00267 { 00268 s << "NULL"; 00269 } 00270 // escape " into \" 00271 breakLinesAndGraphViz(s.str(), o); 00272 } 00273 o << "\";" << std::endl; 00274 00275 // models in this subgraph 00276 { 00277 for(ModelType t = MT_IN; t <= MT_OUTPROJ; t = static_cast<ModelType>(static_cast<unsigned>(t)+1)) 00278 { 00279 const ModelList& modelsAt = mg.modelsAt(u, t); 00280 typename ModelList::const_iterator mit; 00281 for(mit = modelsAt.begin(); mit != modelsAt.end(); ++mit) 00282 { 00283 if( printModels.find(*mit) == printModels.end() ) 00284 continue; 00285 00286 Model m = *mit; 00287 o << "m" << m << "[label=\""; 00288 { 00289 std::stringstream s; 00290 s << toString(mg.propsOf(m).type) << " " << m << " @" << mg.propsOf(m).location << "\\n"; 00291 if( mg.propsOf(m).interpretation != 0 ) 00292 s << *mg.propsOf(m).interpretation; 00293 breakLinesAndGraphViz(s.str(), o); 00294 } 00295 o << "\"];" << std::endl; 00296 00297 // model dependencies (preds) 00298 ModelPredecessorIterator pit, pbegin, pend; 00299 boost::tie(pbegin, pend) = mg.getPredecessors(m); 00300 for(pit = pbegin; pit != pend; ++pit) 00301 { 00302 odeps << 00303 "m" << m << " -> m" << mg.targetOf(*pit) << 00304 "[label=\"" << mg.propsOf(*pit).joinOrder << "\"];" << std::endl; 00305 } 00306 } // through all models 00307 } 00308 } 00309 o << "}" << std::endl; 00310 00311 /* 00312 // unit dependencies 00313 typename EvalGraphT::PredecessorIterator pit, pbegin, pend; 00314 boost::tie(pbegin, pend) = eg.getPredecessors(u); 00315 for(pit = pbegin; pit != pend; ++pit) 00316 { 00317 LOG(INFO,"-> depends on unit " << eg.targetOf(*pit) << "/join order " << eg.propsOf(*pit).joinOrder); 00318 } 00319 */ 00320 00321 } 00322 00323 // deps between models 00324 o << odeps.str() << std::endl; 00325 o << "}" << std::endl; 00326 } 00327 00328 typedef OnlineModelBuilder<FinalEvalGraph> FinalOnlineModelBuilder; 00329 typedef OfflineModelBuilder<FinalEvalGraph> FinalOfflineModelBuilder; 00330 00331 class AbovePluginAtom: 00332 public dlvhex::PluginAtom 00333 { 00334 public: 00335 AbovePluginAtom(): 00336 dlvhex::PluginAtom("above", true) 00337 { 00338 addInputPredicate(); 00339 addInputConstant(); 00340 outputSize = 1; 00341 } 00342 00343 virtual void retrieve(const Query& q, Answer& a) throw (dlvhex::PluginError) 00344 { 00345 // get inputs 00346 assert(q.input.size() == 2); 00347 ID pred = q.input[0]; 00348 ID cmp = q.input[1]; 00349 LOG(INFO,"calculating above extatom for predicate " << pred << " and symbol " << cmp); 00350 const Term& cmpt = registry->terms.getByID(cmp); 00351 00352 // get query 00353 assert(q.pattern.size() == 1); 00354 ID out = q.pattern.front(); 00355 00356 // build set of found targets 00357 assert(q.interpretation != 0); 00358 dlvhex::OrdinaryAtomTable::PredicateIterator it, it_end; 00359 assert(registry != 0); 00360 for(boost::tie(it, it_end) = registry->ogatoms.getRangeByPredicateID(pred); 00361 it != it_end; ++it) 00362 { 00363 const dlvhex::OrdinaryAtom& oatom = *it; 00364 00365 // skip ogatoms not present in interpretation 00366 if( !q.interpretation->getFact(registry->ogatoms.getIDByStorage(oatom).address) ) 00367 continue; 00368 00369 // the edge predicate must be unary 00370 assert(oatom.tuple.size() == 2); 00371 const Term& t = registry->terms.getByID(oatom.tuple[1]); 00372 if( t.symbol >= cmpt.symbol ) 00373 { 00374 if( (out.isTerm() && out.isVariableTerm()) || 00375 (out == oatom.tuple[1]) ) 00376 { 00377 Tuple t; 00378 t.push_back(oatom.tuple[1]); 00379 a.get().push_back(t); 00380 } 00381 } 00382 } 00383 } 00384 }; 00385 00386 class SenseNotArmed1PluginAtom: 00387 public dlvhex::PluginAtom 00388 { 00389 public: 00390 SenseNotArmed1PluginAtom(): 00391 dlvhex::PluginAtom("senseNotArmed1", false) 00392 { 00393 addInputPredicate(); 00394 addInputPredicate(); 00395 addInputConstant(); 00396 addInputConstant(); 00397 outputSize = 0; 00398 } 00399 00400 virtual void retrieve(const Query& q, Answer& a) throw (dlvhex::PluginError) 00401 { 00402 #if 0 00403 // get inputs 00404 assert(q.input.size() == 2); 00405 ID pred = q.input[0]; 00406 ID cmp = q.input[1]; 00407 LOG(INFO,"calculating above extatom for predicate " << pred << " and symbol " << cmp); 00408 const Term& cmpt = registry->terms.getByID(cmp); 00409 00410 // get query 00411 assert(q.pattern.size() == 1); 00412 ID out = q.pattern.front(); 00413 00414 // build set of found targets 00415 assert(q.interpretation != 0); 00416 dlvhex::OrdinaryAtomTable::PredicateIterator it, it_end; 00417 assert(registry != 0); 00418 for(boost::tie(it, it_end) = registry->ogatoms.getRangeByPredicateID(pred); 00419 it != it_end; ++it) 00420 { 00421 const dlvhex::OrdinaryAtom& oatom = *it; 00422 00423 // skip ogatoms not present in interpretation 00424 if( !q.interpretation->getFact(registry->ogatoms.getIDByStorage(oatom).address) ) 00425 continue; 00426 00427 // the edge predicate must be unary 00428 assert(oatom.tuple.size() == 2); 00429 const Term& t = registry->terms.getByID(oatom.tuple[1]); 00430 if( t.symbol >= cmpt.symbol ) 00431 { 00432 if( (out.isTerm() && out.isVariableTerm()) || 00433 (out == oatom.tuple[1]) ) 00434 { 00435 Tuple t; 00436 t.push_back(oatom.tuple[1]); 00437 a.get().push_back(t); 00438 } 00439 } 00440 } 00441 #endif 00442 throw std::runtime_error("todo implement SenseNotArmed1PluginAtom::retrieve"); 00443 } 00444 }; 00445 00446 class SenseNotArmed2PluginAtom: 00447 public dlvhex::PluginAtom 00448 { 00449 public: 00450 SenseNotArmed2PluginAtom(): 00451 dlvhex::PluginAtom("senseNotArmed2", false) 00452 { 00453 outputSize = 0; 00454 addInputPredicate(); 00455 addInputPredicate(); 00456 addInputConstant(); 00457 } 00458 00459 virtual void retrieve(const Query& q, Answer& a) throw (dlvhex::PluginError) 00460 { 00461 // get inputs 00462 assert(q.input.size() == 3); 00463 ID preddisarm = q.input[0]; 00464 ID predlook = q.input[1]; 00465 ID time = q.input[2]; 00466 LOG(INFO,"calculating senseNotArmed2 extatom for " << preddisarm << "/" << predlook << "/" << time); 00467 00468 // get outputs 00469 assert(q.pattern.size() == 0); 00470 00471 // check if <preddisarm>(time) and <predlook>(time) part of interpretation 00472 Tuple tdisarm; 00473 tdisarm.push_back(preddisarm); 00474 tdisarm.push_back(time); 00475 ID iddisarm = registry->ogatoms.getIDByTuple(tdisarm); 00476 00477 Tuple tlook; 00478 tlook.push_back(predlook); 00479 tlook.push_back(time); 00480 ID idlook = registry->ogatoms.getIDByTuple(tlook); 00481 00482 if( iddisarm == ID_FAIL || idlook == ID_FAIL ) 00483 { 00484 // cannot be part of interpretation -> return no tuple as condition not true 00485 return; 00486 } 00487 00488 // check interpretation 00489 assert(q.interpretation != 0); 00490 if( q.interpretation->getFact(iddisarm.address) && 00491 q.interpretation->getFact(idlook.address) ) 00492 { 00493 // found both facts 00494 Tuple t; 00495 a.get().push_back(t); 00496 } 00497 } 00498 }; 00499 00500 class GenPluginAtom1: 00501 public dlvhex::PluginAtom 00502 { 00503 public: 00504 GenPluginAtom1(const std::string& name, unsigned arity): 00505 dlvhex::PluginAtom(name, false) 00506 { 00507 addInputPredicate(); 00508 outputSize = arity; 00509 } 00510 00511 virtual void retrieve(const Query& q, Answer& a) throw (dlvhex::PluginError) 00512 { 00513 // get input 00514 assert(q.input.size() == 1); 00515 ID pred = q.input[0]; 00516 00517 // get outputs 00518 assert(q.pattern.size() == outputSize); 00519 00520 // build unifier 00521 OrdinaryAtom unifier(ID::MAINKIND_ATOM | ID::SUBKIND_ATOM_ORDINARYN); 00522 unifier.tuple.push_back(pred); 00523 unifier.tuple.insert(unifier.tuple.begin(), q.pattern.begin(), q.pattern.end()); 00524 00525 // check if <pred>(pattern) part of interpretation (=forward <pred> via external atom) 00526 assert(q.interpretation != 0); 00527 const Interpretation::Storage& bits = q.interpretation->getStorage(); 00528 for(Interpretation::Storage::enumerator it = bits.first(); 00529 it != bits.end(); ++it) 00530 { 00531 const OrdinaryAtom& ogatom = registry->ogatoms.getByID(ID(ID::MAINKIND_ATOM | ID::SUBKIND_ATOM_ORDINARYG, *it)); 00532 if( ogatom.unifiesWith(unifier) ) 00533 { 00534 Tuple partial; 00535 partial.insert(partial.begin(), ogatom.tuple.begin()+1, ogatom.tuple.end()); 00536 a.get().push_back(partial); 00537 } 00538 } 00539 } 00540 }; 00541 00542 class GenPluginAtom2: 00543 public dlvhex::PluginAtom 00544 { 00545 public: 00546 GenPluginAtom2(const std::string& name, unsigned arity): 00547 dlvhex::PluginAtom(name, false) 00548 { 00549 outputSize = 0; 00550 addInputPredicate(); 00551 for(unsigned u = 0; u < arity; ++u) 00552 addInputPredicate(); 00553 } 00554 00555 virtual void retrieve(const Query& q, Answer& a) throw (dlvhex::PluginError) 00556 { 00557 // get input 00558 assert(checkInputArity(q.input.size())); 00559 assert(checkOutputArity(getExtSourceProperties(), q.pattern.size())); 00560 00561 ID idoutput = registry->ogatoms.getIDByTuple(q.input); 00562 // no ogatom -> cannot be in interpretation 00563 if( idoutput == ID_FAIL ) 00564 return; 00565 00566 assert(q.interpretation != 0); 00567 if( q.interpretation->getFact(idoutput.address) ) 00568 { 00569 // success = found = true! 00570 a.get().push_back(Tuple()); 00571 } 00572 } 00573 }; 00574 00575 int main(int argn, char** argv) 00576 { 00577 try 00578 { 00579 00580 DLVHEX_BENCHMARK_REGISTER_AND_START(sidoverall, "overall timing"); 00581 00582 if( argn != 5 ) 00583 { 00584 std::cerr << "usage: " << argv[0] << " <heurimode> <mbmode> <backend> <inputfile>" << std::endl; 00585 return -1; 00586 } 00587 00588 // 00589 // setup benchmarking 00590 // 00591 benchmark::BenchmarkController& ctr = 00592 benchmark::BenchmarkController::Instance(); 00593 ctr.setOutput(&std::cerr); 00594 // for continuous statistics output, display every 1000'th output 00595 ctr.setPrintInterval(999); 00596 // deconstruct benchmarking (= output results) at scope exit 00597 int dummy; // this is needed, as SCOPE_EXIT is not defined for no arguments 00598 BOOST_SCOPE_EXIT( (dummy) ) { 00599 (void)dummy; 00600 benchmark::BenchmarkController::finish(); 00601 } 00602 BOOST_SCOPE_EXIT_END 00603 00604 // 00605 // preprocess arguments 00606 // 00607 const std::string heurimode(argv[1]); 00608 const std::string mbmode(argv[2]); 00609 const std::string backend(argv[3]); 00610 const std::string fname(argv[4]); 00611 00612 // get input 00613 InputProviderPtr ip(new InputProvider); 00614 ip->addFileInput(fname); 00615 00616 // don't rewrite 00617 00618 // prepare program context 00619 ProgramCtx ctx; 00620 { 00621 RegistryPtr registry(new Registry); 00622 ctx.setupRegistry(registry); 00623 PluginContainerPtr pluginContainer(new PluginContainer); 00624 ctx.setupPluginContainer(pluginContainer); 00625 } 00626 00627 // create all testing plugin atoms 00628 ctx.addPluginAtom(PluginAtomPtr(new AbovePluginAtom)); 00629 ctx.addPluginAtom(PluginAtomPtr(new SenseNotArmed1PluginAtom)); 00630 ctx.addPluginAtom(PluginAtomPtr(new SenseNotArmed2PluginAtom)); 00631 ctx.addPluginAtom(PluginAtomPtr(new GenPluginAtom2("gen2",2))); 00632 00633 // parse HEX program 00634 LOG(INFO,"parsing HEX program"); 00635 DLVHEX_BENCHMARK_REGISTER_AND_START(sidhexparse, "HexParser::parse"); 00636 ModuleHexParser parser; 00637 parser.parse(ip, ctx); 00638 DLVHEX_BENCHMARK_STOP(sidhexparse); 00639 00640 ctx.associateExtAtomsWithPluginAtoms(ctx.idb,true); 00641 00642 //LOG_REGISTRY_PROGRAM(ctx); 00643 00644 // create dependency graph 00645 LOG(INFO,"creating dependency graph"); 00646 DLVHEX_BENCHMARK_REGISTER_AND_START(siddepgraph, "create dependencygraph"); 00647 std::vector<dlvhex::ID> auxRules; 00648 dlvhex::DependencyGraph depgraph(ctx, ctx.registry()); 00649 depgraph.createDependencies(ctx.idb, auxRules); 00650 DLVHEX_BENCHMARK_STOP(siddepgraph); 00651 #ifndef NDEBUG 00652 writeGraphViz(depgraph, fname+"PlainHEXDepGraph"); 00653 #endif 00654 00655 // create component graph 00656 LOG(INFO,"creating component graph"); 00657 DLVHEX_BENCHMARK_REGISTER_AND_START(sidcompgraph, "create componentgraph"); 00658 dlvhex::ComponentGraph compgraph(depgraph, ctx, ctx.registry()); 00659 DLVHEX_BENCHMARK_STOP(sidcompgraph); 00660 #ifndef NDEBUG 00661 writeGraphViz(compgraph, fname+"PlainHEXCompGraph"); 00662 #endif 00663 00664 // manage external evaluation configuration / backend 00665 ASPSolverManager::SoftwareConfigurationPtr externalEvalConfig; 00666 if( backend == "dlv" ) 00667 { 00668 externalEvalConfig.reset(new ASPSolver::DLVSoftware::Configuration); 00669 } 00670 else if( backend == "libdlv" ) 00671 { 00672 #ifdef HAVE_LIBDLV 00673 externalEvalConfig.reset(new ASPSolver::DLVLibSoftware::Configuration); 00674 #else 00675 std::cerr << "sorry, libdlv not compiled in" << std::endl; 00676 return -1; 00677 #endif // HAVE_LIBDLV 00678 } 00679 else if( backend == "libclingo" ) 00680 { 00681 #ifdef HAVE_LIBCLINGO 00682 externalEvalConfig.reset(new ASPSolver::ClingoSoftware::Configuration); 00683 #else 00684 std::cerr << "sorry, libclingo not compiled in" << std::endl; 00685 return -1; 00686 #endif // HAVE_LIBCLINGO 00687 } 00688 else 00689 { 00690 std::cerr << "usage: <backend> must be one of 'dlv','libdlv','libclingo'" << std::endl; 00691 return -1; 00692 } 00693 00694 // create eval graph 00695 LOG(INFO,"creating eval graph"); 00696 DLVHEX_BENCHMARK_REGISTER_AND_START(sidevalgraph, "create evalgraph"); 00697 FinalEvalGraph evalgraph; 00698 EvalGraphBuilder egbuilder(ctx, compgraph, evalgraph, externalEvalConfig); 00699 00700 // use one of several heuristics 00701 if( heurimode == "old" ) 00702 { 00703 // old DLVHEX heuristic 00704 LOG(INFO,"building eval graph with old heuristics"); 00705 EvalHeuristicOldDlvhex heuristicOldDlvhex; 00706 heuristicOldDlvhex.build(egbuilder); 00707 } 00708 else if( heurimode == "trivial" ) 00709 { 00710 // trivial heuristic: just take component graph 00711 // (maximum number of eval units, probably large overhead) 00712 LOG(INFO,"building eval graph with trivial heuristics"); 00713 EvalHeuristicTrivial heuristic; 00714 heuristic.build(egbuilder); 00715 } 00716 else if( heurimode == "easy" ) 00717 { 00718 // easy heuristic: just make some easy adjustments to improve on the trivial heuristics 00719 LOG(INFO,"building eval graph with easy heuristics"); 00720 EvalHeuristicEasy heuristic; 00721 heuristic.build(egbuilder); 00722 } 00723 else 00724 { 00725 std::cerr << "usage: <heurimode> must be one of 'old','trivial','easy'" << std::endl; 00726 return -1; 00727 } 00728 DLVHEX_BENCHMARK_STOP(sidevalgraph); 00729 00730 #ifndef NDEBUG 00731 writeGraphViz(compgraph, fname+"PlainHEXEvalGraph"); 00732 #endif 00733 00734 // setup final unit 00735 LOG(INFO,"setting up final unit"); 00736 DLVHEX_BENCHMARK_REGISTER_AND_START(sidfinalunit, "creating final unit"); 00737 EvalUnit ufinal; 00738 { 00739 ufinal = evalgraph.addUnit(FinalEvalGraph::EvalUnitPropertyBundle()); 00740 LOG(INFO,"ufinal = " << ufinal); 00741 00742 FinalEvalGraph::EvalUnitIterator it, itend; 00743 boost::tie(it, itend) = evalgraph.getEvalUnits(); 00744 for(; it != itend && *it != ufinal; ++it) 00745 { 00746 DBGLOG(DBG,"adding dependency from ufinal to unit " << *it << " join order " << *it); 00747 // we can do this because we know that eval units (= vertices of a vecS adjacency list) are unsigned integers 00748 evalgraph.addDependency(ufinal, *it, FinalEvalGraph::EvalUnitDepPropertyBundle(*it)); 00749 } 00750 } 00751 DLVHEX_BENCHMARK_STOP(sidfinalunit); 00752 00753 // prepare for output 00754 //GenericOutputBuilder ob; 00755 #warning reactivate and redesign outputbuilder 00756 00757 //std::cerr << __FILE__ << ":" << __LINE__ << std::endl << *ctx.registry() << std::endl; 00758 00759 // evaluate 00760 LOG(INFO,"evaluating"); 00761 DLVHEX_BENCHMARK_REGISTER(sidoutputmodel, "output model"); 00762 dlvhex::ModelBuilderConfig<FinalEvalGraph> mbcfg(evalgraph); 00763 if( mbmode == "online" ) 00764 { 00765 typedef FinalOnlineModelBuilder::Model Model; 00766 typedef FinalOnlineModelBuilder::OptionalModel OptionalModel; 00767 typedef FinalOfflineModelBuilder::MyModelGraph MyModelGraph; 00768 LOG(INFO,"creating model builder"); 00769 DLVHEX_BENCHMARK_REGISTER_AND_START(sidonlinemb, "create online mb"); 00770 00771 FinalOnlineModelBuilder mb(mbcfg); 00772 DLVHEX_BENCHMARK_STOP(sidonlinemb); 00773 00774 // get and print all models 00775 OptionalModel m; 00776 DLVHEX_BENCHMARK_REGISTER(sidgetnextonlinemodel, "get next online model"); 00777 unsigned mcount = 0; 00778 do 00779 { 00780 DBGLOG(DBG,"requesting model"); 00781 DLVHEX_BENCHMARK_START(sidgetnextonlinemodel); 00782 m = mb.getNextIModel(ufinal); 00783 DLVHEX_BENCHMARK_STOP(sidgetnextonlinemodel); 00784 if( !!m ) 00785 { 00786 InterpretationConstPtr interpretation = 00787 mb.getModelGraph().propsOf(m.get()).interpretation; 00788 #ifndef NDEBUG 00789 DBGLOG(DBG,"got model#" << mcount << ":" << *interpretation); 00790 std::set<Model> onlyFor; 00791 onlyFor.insert(m.get()); 00792 GraphVizFunc func = boost::bind(&writeEgMgGraphViz<MyModelGraph>, _1, 00793 true, boost::cref(mb.getEvalGraph()), boost::cref(mb.getModelGraph()), onlyFor); 00794 std::stringstream smodel; 00795 smodel << fname << "PlainHEXOnlineModel" << mcount; 00796 writeGraphVizFunctors(func, func, smodel.str()); 00797 #endif 00798 mcount++; 00799 00800 // output model 00801 { 00802 std::cout << *interpretation << std::endl; 00803 } 00804 //std::cerr << __FILE__ << ":" << __LINE__ << std::endl << *ctx.registry() << std::endl; 00805 00806 #ifndef NDEBUG 00807 mb.printEvalGraphModelGraph(std::cerr); 00808 #endif 00809 } 00810 } 00811 while( !!m ); 00812 #ifndef NDEBUG 00813 mb.printEvalGraphModelGraph(std::cerr); 00814 #endif 00815 #ifndef NDEBUG 00816 GraphVizFunc func = boost::bind(&writeEgMgGraphViz<MyModelGraph>, _1, 00817 true, boost::cref(mb.getEvalGraph()), boost::cref(mb.getModelGraph()), boost::none); 00818 writeGraphVizFunctors(func, func, fname+"PlainHEXOnlineEgMg"); 00819 #endif 00820 //std::cerr << __FILE__ << ":" << __LINE__ << std::endl << *ctx.registry() << std::endl; 00821 00822 DLVHEX_BENCHMARK_STOP(sidoverall); 00823 std::cerr << "TIMING " << fname << " " << heurimode << " " << mbmode << " " << backend << " " << 00824 evalgraph.countEvalUnits() << " evalunits " << evalgraph.countEvalUnitDeps() << " evalunitdeps " << mcount << " models "; 00825 benchmark::BenchmarkController::Instance().printDuration(std::cerr, sidoverall) << std::endl; 00826 } 00827 else if( mbmode == "offline" ) 00828 { 00829 typedef FinalOfflineModelBuilder::Model Model; 00830 typedef FinalOfflineModelBuilder::OptionalModel OptionalModel; 00831 typedef FinalOfflineModelBuilder::MyModelGraph MyModelGraph; 00832 00833 LOG(INFO,"creating model builder"); 00834 DLVHEX_BENCHMARK_REGISTER_AND_START(sidofflinemb, "create offline mb"); 00835 FinalOfflineModelBuilder mb(mbcfg); 00836 DLVHEX_BENCHMARK_STOP(sidofflinemb); 00837 00838 LOG(INFO,"creating all final imodels"); 00839 DLVHEX_BENCHMARK_REGISTER_AND_START(sidofflinemodels, "create offline models"); 00840 mb.buildIModelsRecursively(ufinal); 00841 DLVHEX_BENCHMARK_STOP(sidofflinemodels); 00842 #ifndef NDEBUG 00843 mb.printEvalGraphModelGraph(std::cerr); 00844 #endif 00845 00846 LOG(INFO,"printing models"); 00847 DLVHEX_BENCHMARK_REGISTER_AND_START(sidprintoffmodels, "print offline models"); 00848 MyModelGraph& mg = mb.getModelGraph(); 00849 const MyModelGraph::ModelList& models = mg.modelsAt(ufinal, MT_IN); 00850 unsigned mcount = 0; 00851 00852 BOOST_FOREACH(Model m, models) 00853 { 00854 InterpretationConstPtr interpretation = 00855 mg.propsOf(m).interpretation; 00856 #ifndef NDEBUG 00857 DBGLOG(DBG,"got model#" << mcount << ":" << *interpretation); 00858 std::set<Model> onlyFor; 00859 onlyFor.insert(m); 00860 GraphVizFunc func = boost::bind(&writeEgMgGraphViz<MyModelGraph>, _1, 00861 true, boost::cref(mb.getEvalGraph()), boost::cref(mb.getModelGraph()), onlyFor); 00862 std::stringstream smodel; 00863 smodel << fname << "PlainHEXOfflineModel" << mcount; 00864 writeGraphVizFunctors(func, func, smodel.str()); 00865 #endif 00866 mcount++; 00867 00868 // output model 00869 { 00870 std::cout << *interpretation << std::endl; 00871 } 00872 } 00873 DLVHEX_BENCHMARK_STOP(sidprintoffmodels); 00874 #ifndef NDEBUG 00875 GraphVizFunc func = boost::bind(&writeEgMgGraphViz<MyModelGraph>, _1, 00876 true, boost::cref(mb.getEvalGraph()), boost::cref(mb.getModelGraph()), boost::none); 00877 writeGraphVizFunctors(func, func, fname+"PlainHEXOfflineEgMg"); 00878 #endif 00879 00880 DLVHEX_BENCHMARK_STOP(sidoverall); 00881 std::cerr << "TIMING " << fname << " " << heurimode << " " << mbmode << " " << backend << " " << 00882 evalgraph.countEvalUnits() << " evalunits " << evalgraph.countEvalUnitDeps() << " evalunitdeps " << mcount << " models "; 00883 benchmark::BenchmarkController::Instance().printDuration(std::cerr, sidoverall) << "s" << std::endl; 00884 } 00885 else 00886 { 00887 std::cerr << "usage: <mbmode> must be one of 'online','offline'" << std::endl; 00888 return -1; 00889 } 00890 return 0; 00891 00892 } 00893 catch(const std::exception& e) 00894 { 00895 std::cerr << "exception: " << e.what() << std::endl; 00896 return -1; 00897 } 00898 } 00899