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 00128 #ifdef HAVE_CONFIG_H 00129 #include "config.h" 00130 #endif // HAVE_CONFIG_H 00131 00132 #include "dlvhex2/Error.h" 00133 #include "dlvhex2/Benchmarking.h" 00134 #include "dlvhex2/ProgramCtx.h" 00135 #include "dlvhex2/Registry.h" 00136 #include "dlvhex2/PluginContainer.h" 00137 #include "dlvhex2/ASPSolverManager.h" 00138 #include "dlvhex2/ASPSolver.h" 00139 #include "dlvhex2/AnswerSetPrinterCallback.h" 00140 #include "dlvhex2/State.h" 00141 #include "dlvhex2/EvalGraphBuilder.h" 00142 #include "dlvhex2/EvalHeuristicBase.h" 00143 #include "dlvhex2/EvalHeuristicASP.h" 00144 #include "dlvhex2/EvalHeuristicOldDlvhex.h" 00145 #include "dlvhex2/EvalHeuristicTrivial.h" 00146 #include "dlvhex2/EvalHeuristicEasy.h" 00147 #include "dlvhex2/EvalHeuristicGreedy.h" 00148 #include "dlvhex2/EvalHeuristicMonolithic.h" 00149 #include "dlvhex2/EvalHeuristicFromFile.h" 00150 #include "dlvhex2/ExternalAtomEvaluationHeuristics.h" 00151 #include "dlvhex2/UnfoundedSetCheckHeuristics.h" 00152 #include "dlvhex2/OnlineModelBuilder.h" 00153 #include "dlvhex2/OfflineModelBuilder.h" 00154 00155 // internal plugins 00156 #include "dlvhex2/QueryPlugin.h" 00157 #include "dlvhex2/AggregatePlugin.h" 00158 #include "dlvhex2/ChoicePlugin.h" 00159 #include "dlvhex2/ConditionalLiteralPlugin.h" 00160 #include "dlvhex2/StrongNegationPlugin.h" 00161 #include "dlvhex2/HigherOrderPlugin.h" 00162 #include "dlvhex2/WeakConstraintPlugin.h" 00163 #include "dlvhex2/ManualEvalHeuristicsPlugin.h" 00164 #include "dlvhex2/FunctionPlugin.h" 00165 #ifdef HAVE_PYTHON 00166 #include "dlvhex2/PythonPlugin.h" 00167 #endif 00168 00169 #include <getopt.h> 00170 #include <signal.h> 00171 #include <sys/types.h> 00172 #ifdef WIN32 00173 #include <windows.h> 00174 #undef ERROR // there is a clash with a Windows definition 00175 #elif POSIX 00176 #include <pwd.h> 00177 #else 00178 #error Either POSIX or WIN32 must be defined 00179 #endif 00180 00181 #include <boost/tokenizer.hpp> 00182 #include <boost/foreach.hpp> 00183 #include <boost/lexical_cast.hpp> 00184 00185 #include <iostream> 00186 #include <fstream> 00187 #include <sstream> 00188 #include <cstring> 00189 00190 DLVHEX_NAMESPACE_USE 00191 00195 void 00196 printLogo() 00197 { 00198 std::cout 00199 << "DLVHEX " 00200 #ifdef HAVE_CONFIG_H 00201 << VERSION << " " 00202 #endif // HAVE_CONFIG_H 00203 << "[build " 00204 << __DATE__ 00205 #ifdef __GNUC__ 00206 << " gcc " << __VERSION__ 00207 #endif 00208 << "]" << std::endl 00209 << std::endl; 00210 } 00211 00212 00216 void 00217 printUsage(std::ostream &out, const char* whoAmI, bool full) 00218 { 00219 // 123456789-123456789-123456789-123456789-123456789-123456789-123456789-123456789- 00220 out << "Usage: " << whoAmI 00221 << " [OPTION] FILENAME [FILENAME ...]" << std::endl 00222 << std::endl; 00223 00224 out << " or: " << whoAmI 00225 << " [OPTION] --" << std::endl 00226 << std::endl; 00227 00228 if (!full) { 00229 out << "Specify -h or --help for more detailed usage information." << std::endl 00230 << std::endl; 00231 00232 return; 00233 } 00234 00235 // 00236 // As soos as we have more options, we can introduce sections here! 00237 // 00238 // 123456789-123456789-123456789-123456789-123456789-123456789-123456789-123456789- 00239 out << "Input, Output and Reasoning Options (influence the results):" << std::endl 00240 << " -- Parse from stdin." << std::endl 00241 << " -s, --silent Do not display anything than the actual result." << std::endl 00242 << " -f, --filter=foo[,bar[,...]]" << std::endl 00243 << " Only display instances of the specified predicate(s)." << std::endl 00244 << " --nofacts Do not output EDB facts." << std::endl 00245 << " -n, --number=<num> Limit number of displayed models to <num>, 0 (default) means all." << std::endl 00246 << " -N, --maxint=<num> Set maximum integer (#maxint in the program takes precedence over the parameter)." << std::endl 00247 << " --weaksafety Skip strong safety check." << std::endl 00248 << " --strongsafety Applies traditional strong safety criteria." << std::endl 00249 << " --liberalsafety Uses more liberal safety conditions than strong safety (default)." << std::endl 00250 << " --mlp Use dlvhex+mlp solver (modular nonmonotonic logic programs)." << std::endl 00251 << " --forget Forget previous instantiations that are not involved in current computation (mlp setting)." << std::endl 00252 << " --split Use instantiation splitting techniques." << std::endl 00253 << " --noeval Just parse the program, don't evaluate it (only useful with --verbose)." << std::endl 00254 << " --keepnsprefix Keep specified namespace-prefixes in the result." << std::endl 00255 << " --keepauxpreds Keep auxiliary predicates in answer sets." << std::endl 00256 << " --csvinput=PREDICATE,FILENAME" << std::endl 00257 << " Read from the given file in CSV format and add each line as fact" << std::endl 00258 << " in over the specified predicate (the original line number is added as first argument)." << std::endl 00259 << " --cvsoutput=PREDICATE" << std::endl 00260 << " Print the extension of the specified predicate in CSV format." << std::endl 00261 << " They are sorted by their first argument (should be numeric)." << std::endl 00262 << " Answer Sets are separated by empty lines." << std::endl 00263 << " --waitonmodel Wait for newline from stdin after each model." << std::endl 00264 00265 << std::endl << "Plugin Options:" << std::endl 00266 << " -p, --plugindir=DIR Specify additional directory where to look for plugin" << std::endl 00267 << " libraries (additionally to the installation plugin-dir" << std::endl 00268 << " and $HOME/.dlvhex/plugins). Start with ! to reset the" << std::endl 00269 << " preset plugin paths, e.g., '!:/lib' will use only /lib/." << std::endl 00270 00271 << std::endl << "Performance Tuning Options:" << std::endl 00272 << " --extlearn[=none,iobehavior,monotonicity,functionality,linearity,neg,user,generalize]" << std::endl 00273 << " Learn nogoods from external atom evaluation (only useful with --solver=genuineii or --solver=genuinegi)." << std::endl 00274 << " none : Deactivate external learning" << std::endl 00275 << " iobehavior : Apply generic rules to learn input-output behavior" << std::endl 00276 << " monotonicity : Apply special rules for monotonic and antimonotonic external atoms" << std::endl 00277 << " (only useful with iobehavior)" << std::endl 00278 << " functionality : Apply special rules for functional external atoms" << std::endl 00279 << " linearity : Apply special rules for external atoms which are linear in all(!) predicate parameters" << std::endl 00280 << " neg : Learn negative information" << std::endl 00281 << " user : Apply user-defined rules for nogood learning" << std::endl 00282 << " generalize : Generalize learned ground nogoods to nonground nogoods" << std::endl 00283 << " By default, all options except \"generalize\" are enabled." << std::endl 00284 << " --supportsets Exploits support sets for evaluation." << std::endl 00285 << " --extinlining Inlines external sources (based on support sets)" << std::endl 00286 << " --evalall Evaluate all external atoms in every compatibility check, even if previous external atoms already failed." << std::endl 00287 << " This makes nogood learning more independent of the sequence of external atom checks." << std::endl 00288 << " Only useful with --extlearn." << std::endl 00289 << " --nongroundnogoods" << std::endl 00290 << " Automatically instantiate learned nonground nogoods." << std::endl 00291 << " --flpcheck=[explicit,ufs,ufsm,aufs,aufsm,none]" << std::endl 00292 << " Sets the strategy used to check if a candidate is a subset-minimal model of the reduct." << std::endl 00293 << " explicit : Compute the reduct and compare its models with the candidate" << std::endl 00294 << " ufs : Use unfounded sets for minimality checking" << std::endl 00295 << " ufsm : Use unfounded sets for minimality checking;" << std::endl 00296 << " do not decompose the program for UFS checking" << std::endl 00297 << " aufs (default) : Use unfounded sets for minimality checking by exploiting assumptions" << std::endl 00298 << " aufsm : Use unfounded sets for minimality checking by exploiting assumptions;" << std::endl 00299 << " do not decompose the program for UFS checking" << std::endl 00300 << " none : Disable the check" << std::endl 00301 << " --flpcriterion=[all,head,e,em,emi,none]" << std::endl 00302 << " Defines the kind of cycles whose absence is exploited for skipping minimality checks." << std::endl 00303 << " all (default) : Exploit head- and e-cycles for skipping minimality checks" << std::endl 00304 << " head : Exploit head-cycles for skipping minimality checks" << std::endl 00305 << " e : Exploit e-cycles for skipping minimality checks" << std::endl 00306 << " em : Exploit e-cycles and (anti)monotonicity of predicate parameters for skipping minimality checks" << std::endl 00307 << " emi : Exploit e-cycles, (anti)monotonicity of predicate parameters and current interpretation for skipping minimality checks" << std::endl 00308 << " none : Do not exploit head- or e-cycles for skipping minimality checks" << std::endl 00309 << " --noflpcriterion Do no apply decision criterion to skip the FLP check." << std::endl 00310 << " (equivalent to --flpcriterion=none)" << std::endl 00311 << " --ufslearn=[none,reduct,ufs]" << std::endl 00312 << " Enable learning from UFS checks (only useful with --flpcheck=[a]ufs[m])." << std::endl 00313 << " none : No learning" << std::endl 00314 << " reduct : Learning is based on the FLP-reduct" << std::endl 00315 << " ufs (default) : Learning is based on the unfounded set" << std::endl 00316 << " --eaevalheuristics=[always,periodic,inputcomplete,eacomplete,post,never]" << std::endl 00317 << " Selects the heuristic for external atom evaluation." << std::endl 00318 << " always : Evaluate whenever possible" << std::endl 00319 << " periodic : Evaluate in regular intervals" << std::endl 00320 << " inputcomplete : Evaluate whenever the input to the external atom is complete" << std::endl 00321 << " eacomplete : Evaluate whenever all atoms relevant for the external atom are assigned" << std::endl 00322 << " post (default) : Only evaluate at the end" << std::endl 00323 << " never : Only evaluate at the end and also ignore custom heuristics provided by plugins" << std::endl 00324 << " Except for heuristics \"never\", custom heuristics provided by external atoms overrule the" << std::endl 00325 << " global heuristics for the particular external atom." << std::endl 00326 << " --ngminimization=[always,alwaysopt,onconflict,onconflictopt]" << std::endl 00327 << " Minimize positive and negative nogoods generated by external learning." << std::endl 00328 << " always : Try to minimize every learned nogood" << std::endl 00329 << " alwaysopt : Like always, but use cache for answers of external atom queries" << std::endl 00330 << " onconflict : Only minimize nogoods that are violated by the current assignment" << std::endl 00331 << " onconflictopt : Like onconflict, but use cache for answers of external atom queries" << std::endl 00332 << " --ngminimizationlimit=N" << std::endl 00333 << " Maximum size of nogoods that will be minimized" << std::endl 00334 << " (only useful with ngminimization)" << std::endl 00335 << " --ufscheckheuristic=[post,max,periodic]" << std::endl 00336 << " Specifies the frequency of unfounded set checks (only useful with --flpcheck=[a]ufs[m])." << std::endl 00337 << " post (default) : Do UFS check only over complete interpretations" << std::endl 00338 << " max : Do UFS check as frequent as possible and over maximal subprograms" << std::endl 00339 << " periodic : Do UFS check in periodic intervals" << std::endl 00340 << " --modelqueuesize=N" << std::endl 00341 << " Size of the model queue, i.e. number of models which can be computed in parallel." << std::endl 00342 << " Default value is 5. The option is only useful for clasp solver." << std::endl 00343 << " --solver=S Use S as ASP engine, where S is one of dlv, dlvdb, libdlv, libclingo, genuineii, genuinegi, genuineic, genuinegc" << std::endl 00344 << " (genuineii=(i)nternal grounder and (i)nternal solver; genuinegi=(g)ringo grounder and (i)nternal solver" << std::endl 00345 << " genuineic=(i)nternal grounder and (c)lasp solver; genuinegc=(g)ringo grounder and (c)lasp solver)." << std::endl 00346 << " --claspconfig=C If clasp is used, configure it with C where C is parsed by clasp config parser, or " << std::endl 00347 << " C is one of the predefined strings frumpy, jumpy, handy, crafty, or trendy." << std::endl 00348 << " -e, --heuristics=H Use H as evaluation heuristics, where H is one of" << std::endl 00349 << " old : Old dlvhex behavior" << std::endl 00350 << " trivial : Use component graph as eval graph (much overhead)" << std::endl 00351 << " easy : Simple heuristics, used for LPNMR2011" << std::endl 00352 << " greedy (default) : Heuristics with advantages for external behavior learning" << std::endl 00353 << " monolithic : Put entire program into one unit" << std::endl 00354 << " manual:<file> : Read 'collapse <idxs> share <idxs>' commands from <file>" << std::endl 00355 << " where component indices <idx> are from '--graphviz=comp'" << std::endl 00356 << " asp:<script> : Use asp program <script> as eval heuristic" << std::endl 00357 << " --forcegc Always use the guess and check model generator." << std::endl 00358 << " -m, --modelbuilder=M Use M as model builder, where M is one of (online,offline)." << std::endl 00359 << " --nocache Do not cache queries to and answers from external atoms." << std::endl 00360 << " --iauxinaux Keep auxiliary input predicates in auxiliary external atom predicates (can increase or decrease efficiency)." << std::endl 00361 << " --constspace Free partial models immediately after using them. This may cause some models." << std::endl 00362 << " to be computed multiple times. (Not with monolithic.)" << std::endl 00363 00364 << std::endl << "Debugging and General Options:" << std::endl 00365 << " --dumpevalplan=F Dump evaluation plan (usable as manual heuristics) to file F." << std::endl 00366 << " --dumpeanogoods=F" << std::endl 00367 << " Dump learned EA nogoods to file F." << std::endl 00368 << " -v, --verbose[=N] Specify verbose category (if option is used without [=N] then default is 1):" << std::endl 00369 << " 1 : Program analysis information (including dot-file)" << std::endl 00370 << " 2 : Program modifications by plugins" << std::endl 00371 << " 4 : Intermediate model generation info" << std::endl 00372 << " 8 : Timing information" << std::endl 00373 << " (only if configured with --enable-benchmark)" << std::endl 00374 << " add values for multiple categories." << std::endl 00375 << " --dumpstats Dump certain benchmarking results and statistics in CSV format." << std::endl 00376 << " (Only if configured with --enable-benchmark.)" << std::endl 00377 << " --graphviz=G Specify comma separated list of graph types to export as .dot files." << std::endl 00378 << " Default is none, graph types are:" << std::endl 00379 << " dep : Dependency Graph (once per program)" << std::endl 00380 << " cycinp : Graph for analysis cyclic predicate inputs (once per G&C-eval unit)" << std::endl 00381 << " comp : Component Graph (once per program)" << std::endl 00382 << " eval : Evaluation Graph (once per program)" << std::endl 00383 << " model : Model Graph (once per program, after end of computation)" << std::endl 00384 << " imodel : Individual Model Graph (once per model)" << std::endl 00385 << " attr : Attribute dependency graph (once per program)" << std::endl 00386 << " --version Show version information." << std::endl; 00387 } 00388 00389 00390 void 00391 printVersion() 00392 { 00393 std::cout << PACKAGE_TARNAME << " " << VERSION << std::endl; 00394 00395 std::cout << "Copyright (C) 2005-2015 Roman Schindlauer, Thomas Krennwallner, Peter Sch\303\274ller, Christoph Redl" << std::endl 00396 << "License LGPLv2+: GNU GPL version 2 or later <http://gnu.org/licenses/lgpl.html>" << std::endl 00397 << "This is free software: you are free to change and redistribute it." << std::endl 00398 << "There is NO WARRANTY, to the extent permitted by law." << std::endl; 00399 00400 std::cout << std::endl; 00401 00402 std::cout << "Homepage: http://www.kr.tuwien.ac.at/research/systems/dlvhex/" << std::endl 00403 << "Support: [email protected]" << std::endl 00404 << "Bug reports: http://github.com/hexhex/core/issues/" << std::endl; 00405 00406 exit(0); 00407 } 00408 00409 00413 void 00414 InternalError (const char *msg) 00415 { 00416 std::cerr << std::endl 00417 << "An internal error occurred (" << msg << ")." 00418 << std::endl 00419 << "Please contact <" PACKAGE_BUGREPORT ">." << std::endl; 00420 exit (99); 00421 } 00422 00423 00424 // config and defaults of dlvhex main 00425 struct Config 00426 { 00427 bool optionNoEval; 00428 bool helpRequested; 00429 std::string optionPlugindir; 00430 #if defined(HAVE_DLVDB) 00431 // dlvdb speciality 00432 std::string typFile; 00433 #endif 00434 // those options unhandled by dlvhex main 00435 std::list<const char*> pluginOptions; 00436 00437 Config(): 00438 optionNoEval(false), 00439 helpRequested(false), 00440 optionPlugindir(""), 00441 #if defined(HAVE_DLVDB) 00442 typFile(), 00443 #endif 00444 pluginOptions() {} 00445 }; 00446 00447 void processOptionsPrePlugin(int argc, char** argv, Config& config, ProgramCtx& pctx); 00448 00449 namespace 00450 { 00451 ProgramCtx* exeCtx = NULL; 00452 } 00453 00454 00455 void signal_handler(int signum) 00456 { 00457 // perform benchmarking shutdown to obtain benchmark output 00458 #ifdef WIN32 00459 LOG(ERROR,"dlvhex2 with pid " << GetCurrentProcessId() << " got termination signal" << signum << "!"); 00460 #else 00461 LOG(ERROR,"dlvhex2 with pid " << getpid() << " got termination signal " << signum << "!"); 00462 #endif 00463 00464 benchmark::BenchmarkController::finish(); 00465 00466 // hard exit 00467 // (otherwise ctrl+c does not work for many situations, which is annoying!) 00468 exit(2); 00469 } 00470 00471 00472 int main(int argc, char *argv[]) 00473 { 00474 const char* whoAmI = argv[0]; 00475 00476 // pre-init logger 00477 // (we use more than 4 bits -> two digit loglevel) 00478 Logger::Instance().setPrintLevelWidth(2); 00479 00480 // program context 00481 ProgramCtx pctx; 00482 exeCtx = &pctx; 00483 { 00484 RegistryPtr registry(new Registry); 00485 PluginContainerPtr pcp(new PluginContainer); 00486 pctx.setupRegistry(registry); 00487 pctx.setupPluginContainer(pcp); 00488 } 00489 00490 // default external asp solver to first one that has been configured 00491 #if HAVE_DLV 00492 pctx.setASPSoftware( 00493 ASPSolverManager::SoftwareConfigurationPtr(new ASPSolver::DLVSoftware::Configuration)); 00494 #else 00495 #if HAVE_DLVDB 00496 #error reactivate dlvdb 00497 //pctx.setASPSoftware( 00498 // ASPSolverManager::SoftwareConfigurationPtr(new ASPSolver::DLVDBSoftware::Configuration)); 00499 #else 00500 #if HAVE_LIBDLV 00501 pctx.setASPSoftware( 00502 ASPSolverManager::SoftwareConfigurationPtr(new ASPSolver::DLVLibSoftware::Configuration)); 00503 #else 00504 #if HAVE_LIBCLINGO 00505 pctx.setASPSoftware( 00506 ASPSolverManager::SoftwareConfigurationPtr(new ASPSolver::ClingoSoftware::Configuration)); 00507 #else 00508 #if defined(HAVE_LIBGRINGO) && defined(HAVE_LIBCLASP) 00509 #else 00510 #ifndef WIN32 00511 #error no asp software configured! configure.ac should not allow this to happen! 00512 #endif 00513 #endif 00514 #endif 00515 #endif 00516 #endif 00517 #endif 00518 00519 // default eval heuristic = "greedy" heuristic 00520 pctx.evalHeuristic.reset(new EvalHeuristicGreedy); 00521 // default model builder = "online" model builder 00522 pctx.modelBuilderFactory = boost::factory<OnlineModelBuilder<FinalEvalGraph>*>(); 00523 00524 // defaults of main 00525 Config config; 00526 00527 // if we throw UsageError inside this, error and usage will be displayed, otherwise only error 00528 int returnCode = 1; 00529 try 00530 { 00531 // default logging priority = errors + warnings 00532 Logger::Instance().setPrintLevels(Logger::ERROR | Logger::WARNING); 00533 00534 // manage options we can already manage 00535 // TODO use boost::program_options 00536 processOptionsPrePlugin(argc, argv, config, pctx); 00537 00538 #ifdef HAVE_PYTHON 00539 PythonPlugin* pythonPlugin = new PythonPlugin(); 00540 #endif 00541 00542 // initialize internal plugins 00543 { 00544 PluginInterfacePtr manualEvalHeuristicsPlugin(new ManualEvalHeuristicsPlugin); 00545 pctx.pluginContainer()->addInternalPlugin(manualEvalHeuristicsPlugin); 00546 PluginInterfacePtr queryPlugin(new QueryPlugin); 00547 pctx.pluginContainer()->addInternalPlugin(queryPlugin); 00548 PluginInterfacePtr aggregatePlugin(new AggregatePlugin); 00549 pctx.pluginContainer()->addInternalPlugin(aggregatePlugin); 00550 PluginInterfacePtr strongNegationPlugin(new StrongNegationPlugin); 00551 pctx.pluginContainer()->addInternalPlugin(strongNegationPlugin); 00552 PluginInterfacePtr higherOrderPlugin(new HigherOrderPlugin); 00553 pctx.pluginContainer()->addInternalPlugin(higherOrderPlugin); 00554 PluginInterfacePtr weakConstraintPlugin(new WeakConstraintPlugin); 00555 pctx.pluginContainer()->addInternalPlugin(weakConstraintPlugin); 00556 PluginInterfacePtr functionPlugin(new FunctionPlugin); 00557 pctx.pluginContainer()->addInternalPlugin(functionPlugin); 00558 PluginInterfacePtr choicePlugin(new ChoicePlugin); 00559 pctx.pluginContainer()->addInternalPlugin(choicePlugin); 00560 PluginInterfacePtr conditionalLiteralPlugin(new ConditionalLiteralPlugin); 00561 pctx.pluginContainer()->addInternalPlugin(conditionalLiteralPlugin); 00562 #ifdef HAVE_PYTHON 00563 PluginInterfacePtr _pythonPlugin(pythonPlugin); 00564 pctx.pluginContainer()->addInternalPlugin(_pythonPlugin); 00565 #endif 00566 } 00567 00568 // before anything else we dump the logo 00569 if( !pctx.config.getOption("Silent") ) 00570 printLogo(); 00571 00572 // initialize benchmarking (--verbose=8) with scope exit 00573 // (this cannot be outsourced due to the scope) 00574 benchmark::BenchmarkController& ctr = 00575 benchmark::BenchmarkController::Instance(); 00576 if( pctx.config.doVerbose(dlvhex::Configuration::PROFILING) ) { 00577 LOG(INFO,"initializing benchmarking output"); 00578 ctr.setOutput(&Logger::Instance().stream()); 00579 // for continuous statistics output, display every 1000'th output 00580 ctr.setPrintInterval(999); 00581 } 00582 else 00583 ctr.setOutput(0); 00584 00585 // also deconstruct & output at SIGTERM/SIGINT 00586 { 00587 if( SIG_ERR == signal(SIGTERM, signal_handler) ) 00588 LOG(WARNING,"setting SIGTERM handler terminated with error '" << strerror(errno)); 00589 if( SIG_ERR == signal(SIGINT, signal_handler) ) 00590 LOG(WARNING,"setting SIINT handler terminated with error '" << strerror(errno)); 00591 } 00592 00593 // startup statemachine 00594 pctx.changeState(StatePtr(new ShowPluginsState)); 00595 00596 // load plugins 00597 { 00598 DLVHEX_BENCHMARK_REGISTER_AND_SCOPE(sid,"loading plugins"); 00599 pctx.pluginContainer()->loadPlugins(config.optionPlugindir); 00600 pctx.showPlugins(); 00601 } 00602 00603 // now we may offer help, including plugin help 00604 if( config.helpRequested ) { 00605 printUsage(std::cerr, whoAmI, true); 00606 pctx.pluginContainer()->printUsage(std::cerr); 00607 return 1; 00608 } 00609 00610 // process plugin options using plugins 00611 // (this deletes processed options from config.pluginOptions) 00612 // TODO use boost::program_options 00613 pctx.processPluginOptions(config.pluginOptions); 00614 if( pctx.terminationRequest ) return 1; 00615 00616 // handle options not recognized by dlvhex and not by plugins 00617 if( !config.pluginOptions.empty() ) { 00618 std::stringstream bad; 00619 bad << "Unknown option(s):"; 00620 BOOST_FOREACH(const char* opt, config.pluginOptions) { 00621 bad << " " << opt; 00622 } 00623 throw UsageError(bad.str()); 00624 } 00625 // use configured plugins to obtain plugin atoms 00626 pctx.addPluginAtomsFromPluginContainer(); 00627 00628 // check if this plugin provides a custom model generator 00629 BOOST_FOREACH(PluginInterfacePtr plugin, pctx.pluginContainer()->getPlugins()) { 00630 if (plugin->providesCustomModelGeneratorFactory(pctx)) { 00631 if (pctx.customModelGeneratorProvider == 0) { 00632 LOG(DBG, "Plugin provides custom model generator factory"); 00633 pctx.customModelGeneratorProvider = plugin; 00634 } 00635 else { 00636 throw PluginError("Multiple plugins prove alternative model generator factories. Do not know which one to use. Please change command-line options."); 00637 } 00638 } 00639 } 00640 00641 #ifdef HAVE_PYTHON 00642 if (pctx.config.getOption("HavePythonMain")) { 00643 pythonPlugin->runPythonMain(pctx.config.getStringOption("PythonMain")); 00644 // display benchmark output 00645 benchmark::BenchmarkController::finish(); 00646 return 1; 00647 } 00648 #endif 00649 00650 // now we check if we got input 00651 if( !pctx.inputProvider || !pctx.inputProvider->hasContent() ) 00652 throw UsageError("no input specified!"); 00653 00654 // convert input (only done if at least one plugin provides a converter) 00655 pctx.convert(); 00656 if( pctx.terminationRequest ) return 1; 00657 00658 // parse input (coming directly from inputprovider or from inputprovider provided by the convert() step) 00659 pctx.parse(); 00660 if( pctx.terminationRequest ) return 1; 00661 00662 // check if in mlp mode 00663 if( pctx.config.getOption("MLP") ) { 00664 // syntax check for mlp 00665 pctx.moduleSyntaxCheck(); 00666 if( pctx.terminationRequest ) return 1; 00667 00668 // solve mlp 00669 pctx.mlpSolver(); 00670 if( pctx.terminationRequest ) return 1; 00671 } 00672 00673 else { 00674 00675 // associate PluginAtom instances with 00676 // ExternalAtom instances (in the IDB) 00677 pctx.associateExtAtomsWithPluginAtoms(pctx.idb, true); 00678 if( pctx.terminationRequest ) return 1; 00679 00680 // rewrite program (plugins might want to do this, e.g., for partial grounding) 00681 pctx.rewriteEDBIDB(); 00682 if( pctx.terminationRequest ) return 1; 00683 00684 // associate PluginAtom instances with 00685 // ExternalAtom instances (in the IDB) 00686 // (again, rewrite might add external atoms) 00687 pctx.associateExtAtomsWithPluginAtoms(pctx.idb, true); 00688 00689 // check weak safety 00690 pctx.safetyCheck(); 00691 if( pctx.terminationRequest ) return 1; 00692 00693 // check liberal safety 00694 pctx.liberalSafetyCheck(); 00695 if( pctx.terminationRequest ) return 1; 00696 00697 // create dependency graph (we need the previous step for this) 00698 pctx.createDependencyGraph(); 00699 if( pctx.terminationRequest ) return 1; 00700 00701 // optimize dependency graph (plugins might want to do this, e.g. by using domain information) 00702 pctx.optimizeEDBDependencyGraph(); 00703 if( pctx.terminationRequest ) return 1; 00704 // everything in the following will be done using the dependency graph and EDB 00705 WARNING("IDB and dependencygraph could get out of sync! should we lock or empty the IDB to ensure that it is not directly used anymore after this step?") 00706 00707 // create graph of strongly connected components of dependency graph 00708 pctx.createComponentGraph(); 00709 if( pctx.terminationRequest ) return 1; 00710 00711 // use SCCs to do strong safety check 00712 if( !pctx.config.getOption("SkipStrongSafetyCheck") ) { 00713 pctx.strongSafetyCheck(); 00714 if( pctx.terminationRequest ) return 1; 00715 } 00716 00717 // select heuristics and create eval graph 00718 pctx.createEvalGraph(); 00719 if( pctx.terminationRequest ) return 1; 00720 00721 // stop here if no evaluation was requested 00722 if( config.optionNoEval ) 00723 return 0; 00724 00725 // setup model builder and configure plugin/dlvhex model processing hooks 00726 pctx.setupProgramCtx(); 00727 if( pctx.terminationRequest ) return 1; 00728 00729 // evaluate (generally done in streaming mode, may exit early if indicated by hooks) 00730 // (individual model output should happen here) 00731 pctx.evaluate(); 00732 if( pctx.terminationRequest ) return 1; 00733 00734 } // end if (mlp) else ... 00735 00736 // finalization plugin/dlvhex hooks (for accumulating model processing) 00737 // (accumulated model output/query answering should happen here) 00738 pctx.postProcess(); 00739 00740 // no error 00741 returnCode = 0; 00742 } 00743 catch(const UsageError &ue) { 00744 std::cerr << "UsageError: " << ue.getErrorMsg() << std::endl << std::endl; 00745 printUsage(std::cerr, whoAmI, true); 00746 if( !!pctx.pluginContainer() ) 00747 pctx.pluginContainer()->printUsage(std::cerr); 00748 } 00749 catch(const GeneralError &ge) { 00750 pctx.modelBuilder.reset(); 00751 std::cerr << "GeneralError: " << ge.getErrorMsg() << std::endl << std::endl; 00752 } 00753 catch(const std::exception& e) { 00754 std::cerr << "Exception: " << e.what() << std::endl << std::endl; 00755 } 00756 00757 // display benchmark output 00758 benchmark::BenchmarkController::finish(); 00759 00760 // regular exit 00761 return returnCode; 00762 } 00763 00764 00765 void configurePluginPath(std::string& userPlugindir); 00766 00767 // process whole commandline: 00768 // * recognized arguments are stored into some config 00769 // * non-option arguments are interpreted as input files 00770 // and used to configure config.inputProvider (exception: .typ files) 00771 // * non-recognized option arguments are stored into config.pluginOptions 00772 void processOptionsPrePlugin( 00773 int argc, char** argv, 00774 Config& config, ProgramCtx& pctx) 00775 { 00776 extern char* optarg; 00777 extern int optind; 00778 extern int opterr; 00779 00780 // 00781 // prevent error message for unknown options - they might be known to 00782 // plugins later! 00783 // 00784 opterr = 0; 00785 00786 int ch; 00787 int longid; 00788 00789 static const char* shortopts = "hsvf:p:are:m:n:N:"; 00790 static struct option longopts[] = { 00791 { "help", no_argument, 0, 'h' }, 00792 { "silent", no_argument, 0, 's' }, 00793 { "verbose", optional_argument, 0, 'v' }, 00794 { "filter", required_argument, 0, 'f' }, 00795 { "plugindir", required_argument, 0, 'p' }, 00796 { "reverse", no_argument, 0, 'r' }, 00797 { "heuristics", required_argument, 0, 'e' }, 00798 { "modelbuilder", required_argument, 0, 'm' }, 00799 { "number", required_argument, 0, 'n' }, 00800 { "maxint", required_argument, 0, 'N' }, 00801 { "weaksafety", no_argument, &longid, 2 }, 00802 { "noeval", no_argument, &longid, 5 }, 00803 { "keepnsprefix", no_argument, &longid, 6 }, 00804 { "solver", required_argument, &longid, 7 }, 00805 { "nocache", no_argument, &longid, 8 }, 00806 { "version", no_argument, &longid, 9 }, 00807 { "graphviz", required_argument, &longid, 10 }, 00808 { "keepauxpreds", no_argument, &longid, 11 }, 00809 { "nofacts", no_argument, &longid, 12 }, 00810 { "mlp", no_argument, &longid, 13 }, 00811 { "forget", no_argument, &longid, 15 }, 00812 { "split", no_argument, &longid, 16 }, 00813 { "dumpevalplan", required_argument, &longid, 17 }, 00814 { "extlearn", optional_argument, 0, 18 }, 00815 { "evalall", no_argument, 0, 19 }, 00816 { "flpcheck", required_argument, 0, 20 }, 00817 { "ufslearn", optional_argument, 0, 23 }, 00818 { "noflpcriterion", no_argument, 0, 35 }, 00819 { "flpcriterion", optional_argument, 0, 42 }, 00820 { "eaevalheuristic", required_argument, 0, 26 }, 00821 { // compatibility 00822 "eaevalheuristics", required_argument, 0, 26 00823 }, 00824 { "ufscheckheuristic", required_argument, 0, 27 }, 00825 { // compatibility 00826 "ufscheckheuristics", required_argument, 0, 27 00827 }, 00828 { // perhaps only temporary 00829 "benchmarkeastderr", no_argument, 0, 28 00830 }, 00831 { // perhaps only temporary 00832 "explicitflpunshift", no_argument, 0, 29 00833 }, 00834 { // perhaps only temporary 00835 "printlearnednogoodsstderr", no_argument, 0, 30 00836 }, 00837 { "nongroundnogoods", no_argument, 0, 31 }, 00838 { "modelqueuesize", required_argument, 0, 32 }, 00839 { "liberalsafety", no_argument, 0, 33 }, 00840 { // perhaps only temporary 00841 "claspconfig", required_argument, 0, 36 00842 }, 00843 { "noclaspincremental", no_argument, 0, 43 }, 00844 { "claspsingletonloopnogoods", no_argument, 0, 44 }, 00845 { "claspinverseliterals", no_argument, 0, 45 }, 00846 { "dumpstats", no_argument, 0, 37 }, 00847 { "iauxinaux", optional_argument, 0, 38 }, 00848 { "legacyecycledetection", no_argument, 0, 46 }, 00849 { "constspace", no_argument, 0, 39 }, 00850 { "forcesinglethreading", no_argument, 0, 40 }, 00851 { "lazyufscheckerinitialization", no_argument, 0, 47 }, 00852 { "supportsets", no_argument, 0, 48 }, 00853 { "forcegc", no_argument, 0, 49 }, 00854 { "incremental", no_argument, 0, 50 }, 00855 { "strongsafety", no_argument, 0, 52 }, 00856 { "optmode", required_argument, 0, 54 }, 00857 { "claspdefernprop", required_argument, 0, 55 }, 00858 { "claspdefermsec", required_argument, 0, 56 }, 00859 { "dumpeanogoods", required_argument, 0, 57 }, 00860 { "ngminimization", required_argument, 0, 58 }, 00861 { "ngminimizationlimit", required_argument, 0, 59 }, 00862 { "csvinput", required_argument, 0, 60 }, 00863 { "csvoutput", required_argument, 0, 61 }, 00864 { "noouterexternalatoms", no_argument, 0, 62 }, 00865 { "transunitlearning", no_argument, 0, 64 }, 00866 { "verifyfromlearned", no_argument, 0, 65 }, 00867 { "waitonmodel", no_argument, 0, 66 }, 00868 { "extinlining", no_argument, 0, 67 }, 00869 { NULL, 0, NULL, 0 } 00870 }; 00871 00872 // default settings 00873 pctx.config.setOption("NoPropagator", 0); 00874 pctx.defaultExternalAtomEvaluationHeuristicsFactory.reset(new ExternalAtomEvaluationHeuristicsNeverFactory()); 00875 pctx.unfoundedSetCheckHeuristicsFactory.reset(new UnfoundedSetCheckHeuristicsPostFactory()); 00876 00877 // start with new input provider 00878 pctx.inputProvider.reset(new InputProvider); 00879 00880 bool specifiedModelQueueSize = false; 00881 bool defiaux = false; 00882 bool iaux = false; 00883 bool heuristicChosen = false; 00884 bool heuristicMonolithic = false; 00885 bool solverSet = false; 00886 bool forceoptmode = false; 00887 while ((ch = getopt_long(argc, argv, shortopts, longopts, NULL)) != -1) { 00888 switch (ch) { 00889 case 'h': 00890 config.helpRequested = 1; 00891 break; 00892 00893 case 's': 00894 pctx.config.setOption("Silent", 1); 00895 break; 00896 00897 case 'v': 00898 if (optarg) { 00899 int level = 1; 00900 try 00901 { 00902 level = boost::lexical_cast<int>(optarg); 00903 } 00904 catch(const boost::bad_lexical_cast&) { 00905 LOG(ERROR,"could not parse verbosity level '" << optarg << "' - using default=" << level << "!"); 00906 } 00907 pctx.config.setOption("Verbose", level); 00908 Logger::Instance().setPrintLevels(level); 00909 } 00910 else { 00911 pctx.config.setOption("Verbose", 1); 00912 Logger::Instance().setPrintLevels(Logger::ERROR | Logger::WARNING | Logger::INFO); 00913 } 00914 break; 00915 00916 case 'f': 00917 { 00918 boost::char_separator<char> sep(","); 00919 // g++ 3.3 is unable to pass that at the ctor line below 00920 std::string oa(optarg); 00921 boost::tokenizer<boost::char_separator<char> > tok(oa, sep); 00922 00923 for(boost::tokenizer<boost::char_separator<char> >::const_iterator f = tok.begin(); 00924 f != tok.end(); ++f) 00925 pctx.config.addFilter(*f); 00926 } 00927 break; 00928 00929 case 'p': 00930 config.optionPlugindir = std::string(optarg); 00931 pctx.config.setStringOption("PluginDirs", std::string(optarg)); 00932 break; 00933 00934 case 'r': 00935 pctx.config.setOption("ReverseOrder", 1); 00936 break; 00937 00938 case 'e': 00939 // heuristics={old,trivial,easy,manual:>filename>} 00940 { 00941 heuristicChosen = true; 00942 std::string heuri(optarg); 00943 if( heuri == "old" ) { 00944 pctx.evalHeuristic.reset(new EvalHeuristicOldDlvhex); 00945 } 00946 else if( heuri == "trivial" ) { 00947 pctx.evalHeuristic.reset(new EvalHeuristicTrivial); 00948 } 00949 else if( heuri == "easy" ) { 00950 pctx.evalHeuristic.reset(new EvalHeuristicEasy); 00951 } 00952 else if( heuri == "greedy" ) { 00953 pctx.evalHeuristic.reset(new EvalHeuristicGreedy); 00954 } 00955 else if( heuri == "monolithic" ) { 00956 pctx.evalHeuristic.reset(new EvalHeuristicMonolithic); 00957 heuristicMonolithic = true; 00958 } 00959 else if( heuri.substr(0,7) == "manual:" ) { 00960 pctx.evalHeuristic.reset(new EvalHeuristicFromFile(heuri.substr(7))); 00961 } 00962 else if( heuri.substr(0,4) == "asp:" ) { 00963 pctx.evalHeuristic.reset(new EvalHeuristicASP(heuri.substr(4))); 00964 } 00965 else { 00966 throw UsageError("unknown evaluation heuristic '" + heuri +"' specified!"); 00967 } 00968 LOG(INFO,"selected '" << heuri << "' evaluation heuristics"); 00969 } 00970 break; 00971 00972 case 'm': 00973 // modelbuilder={offline,online} 00974 { 00975 std::string modelbuilder(optarg); 00976 if( modelbuilder == "offline" ) { 00977 pctx.modelBuilderFactory = 00978 boost::factory<OfflineModelBuilder<FinalEvalGraph>*>(); 00979 } 00980 else if( modelbuilder == "online" ) { 00981 pctx.modelBuilderFactory = 00982 boost::factory<OnlineModelBuilder<FinalEvalGraph>*>(); 00983 } 00984 else { 00985 throw UsageError("unknown model builder '" + modelbuilder +"' specified!"); 00986 } 00987 LOG(INFO,"selected '" << modelbuilder << "' model builder"); 00988 } 00989 break; 00990 00991 case 'n': 00992 { 00993 int models = 0; 00994 try 00995 { 00996 if( optarg[0] == '=' ) 00997 models = boost::lexical_cast<unsigned>(&optarg[1]); 00998 else 00999 models = boost::lexical_cast<unsigned>(optarg); 01000 } 01001 catch(const boost::bad_lexical_cast&) { 01002 LOG(ERROR,"could not parse model count '" << optarg << "' - using default=" << models << "!"); 01003 } 01004 pctx.config.setOption("NumberOfModels", models); 01005 } 01006 break; 01007 01008 case 'N': 01009 { 01010 int maxint = 0; 01011 try 01012 { 01013 if( optarg[0] == '=' ) 01014 maxint = boost::lexical_cast<unsigned>(&optarg[1]); 01015 else 01016 maxint = boost::lexical_cast<unsigned>(optarg); 01017 } 01018 catch(const boost::bad_lexical_cast&) { 01019 LOG(ERROR,"could not parse maxint '" << optarg << "' - using default=" << maxint << "!"); 01020 } 01021 pctx.maxint = maxint; 01022 } 01023 break; 01024 01025 case 0: 01026 switch (longid) { 01027 case 2: 01028 pctx.config.setOption("SkipStrongSafetyCheck",1); 01029 break; 01030 01031 //case 3: 01032 // pctx.setOutputBuilder(new RuleMLOutputBuilder); 01033 // XML output makes only sense with silent: 01034 // pctx.config.setOption("Silent", 1); 01035 // break; 01036 01037 //case 4: 01038 // optiondlt = true; 01039 // break; 01040 01041 case 5: 01042 config.optionNoEval = true; 01043 break; 01044 01045 case 6: 01046 pctx.config.setOption("KeepNamespacePrefix",1); 01047 break; 01048 01049 case 7: 01050 { 01051 std::string solver(optarg); 01052 if( solver == "dlv" ) { 01053 #if defined(HAVE_DLV) 01054 pctx.setASPSoftware( 01055 ASPSolverManager::SoftwareConfigurationPtr(new ASPSolver::DLVSoftware::Configuration)); 01056 pctx.config.setOption("GenuineSolver", 0); 01057 #else 01058 throw GeneralError("sorry, no support for solver backend '"+solver+"' compiled into this binary"); 01059 #endif 01060 } 01061 else if( solver == "dlvdb" ) { 01062 #if defined(HAVE_DLVDB) 01063 WARNING("reactivate dlvhdb") 01064 //pctx.setASPSoftware( 01065 // ASPSolverManager::SoftwareConfigurationPtr(new ASPSolver::DLVDBSoftware::Configuration)); 01066 pctx.config.setOption("GenuineSolver", 0); 01067 #else 01068 throw GeneralError("sorry, no support for solver backend '"+solver+"' compiled into this binary"); 01069 #endif 01070 } 01071 else if( solver == "libdlv" ) { 01072 #if defined(HAVE_LIBDLV) 01073 pctx.setASPSoftware( 01074 ASPSolverManager::SoftwareConfigurationPtr(new ASPSolver::DLVLibSoftware::Configuration)); 01075 pctx.config.setOption("GenuineSolver", 0); 01076 #else 01077 throw GeneralError("sorry, no support for solver backend '"+solver+"' compiled into this binary"); 01078 #endif 01079 } 01080 else if( solver == "libclingo" ) { 01081 #if defined(HAVE_LIBCLINGO) 01082 pctx.setASPSoftware( 01083 ASPSolverManager::SoftwareConfigurationPtr(new ASPSolver::ClingoSoftware::Configuration)); 01084 pctx.config.setOption("GenuineSolver", 0); 01085 #else 01086 throw GeneralError("sorry, no support for solver backend '"+solver+"' compiled into this binary"); 01087 #endif 01088 } 01089 else if( solver == "genuineii" ) { 01090 pctx.config.setOption("GenuineSolver", 1); 01091 } 01092 else if( solver == "genuinegi" ) { 01093 #if defined(HAVE_LIBGRINGO) 01094 pctx.config.setOption("GenuineSolver", 2); 01095 #else 01096 throw GeneralError("sorry, no support for solver backend '"+solver+"' compiled into this binary"); 01097 #endif 01098 } 01099 else if( solver == "genuineic" ) { 01100 #if defined(HAVE_LIBCLASP) 01101 pctx.config.setOption("GenuineSolver", 3); 01102 #else 01103 throw GeneralError("sorry, no support for solver backend '"+solver+"' compiled into this binary"); 01104 #endif 01105 } 01106 else if( solver == "genuinegc" ) { 01107 #if defined(HAVE_LIBGRINGO) && defined(HAVE_LIBCLASP) 01108 pctx.config.setOption("GenuineSolver", 4); 01109 #else 01110 throw GeneralError("sorry, no support for solver backend '"+solver+"' compiled into this binary"); 01111 #endif 01112 } 01113 else { 01114 throw UsageError("unknown solver backend '" + solver +"' specified!"); 01115 } 01116 LOG(INFO,"selected '" << solver << "' solver backend"); 01117 solverSet = true; 01118 } 01119 break; 01120 01121 case 8: 01122 pctx.config.setOption("UseExtAtomCache",0); 01123 break; 01124 01125 case 9: 01126 printVersion(); 01127 break; 01128 01129 case 10: 01130 { 01131 boost::char_separator<char> sep(","); 01132 // g++ 3.3 is unable to pass that at the ctor line below 01133 std::string oa(optarg); 01134 boost::tokenizer<boost::char_separator<char> > tok(oa, sep); 01135 01136 for(boost::tokenizer<boost::char_separator<char> >::const_iterator f = tok.begin(); 01137 f != tok.end(); ++f) { 01138 const std::string& token = *f; 01139 if( token == "dep" ) { 01140 pctx.config.setOption("DumpDepGraph",1); 01141 } 01142 else if( token == "cycinp" ) { 01143 pctx.config.setOption("DumpCyclicPredicateInputAnalysisGraph",1); 01144 } 01145 else if( token == "comp" ) { 01146 pctx.config.setOption("DumpCompGraph",1); 01147 } 01148 else if( token == "eval" ) { 01149 pctx.config.setOption("DumpEvalGraph",1); 01150 } 01151 else if( token == "model" ) { 01152 pctx.config.setOption("DumpModelGraph",1); 01153 throw std::runtime_error("DumpModelGraph not implemented!"); 01154 } 01155 else if( token == "imodel" ) { 01156 pctx.config.setOption("DumpIModelGraph",1); 01157 throw std::runtime_error("DumpIModelGraph not implemented!"); 01158 } 01159 else if( token == "attr" ) { 01160 pctx.config.setOption("DumpAttrGraph",1); 01161 } 01162 else 01163 throw UsageError("unknown graphviz graph type '"+token+"'"); 01164 } 01165 } 01166 break; 01167 case 11: 01168 pctx.config.setOption("KeepAuxiliaryPredicates",1); 01169 break; 01170 case 12: 01171 pctx.config.setOption("NoFacts",1); 01172 break; 01173 case 13: 01174 pctx.config.setOption("MLP",1); 01175 break; 01176 // unused case 14: 01177 case 15: 01178 pctx.config.setOption("Forget",1); 01179 break; 01180 case 16: 01181 pctx.config.setOption("Split",1); 01182 break; 01183 case 17: 01184 { 01185 std::string fname(optarg); 01186 pctx.config.setOption("DumpEvaluationPlan",1); 01187 pctx.config.setStringOption("DumpEvaluationPlanFile",fname); 01188 } 01189 break; 01190 } 01191 break; 01192 01193 case 18: 01194 { 01195 // overwrite default settings: assume that nothing is enabled 01196 pctx.config.setOption("ExternalLearningIOBehavior", 0); 01197 pctx.config.setOption("ExternalLearningMonotonicity", 0); 01198 pctx.config.setOption("ExternalLearningFunctionality", 0); 01199 pctx.config.setOption("ExternalLearningLinearity", 0); 01200 pctx.config.setOption("ExternalLearningNeg", 0); 01201 pctx.config.setOption("ExternalLearningUser", 0); 01202 01203 bool noneToken = false; 01204 bool enableToken = false; 01205 if (optarg) { 01206 boost::char_separator<char> sep(","); 01207 // g++ 3.3 is unable to pass that at the ctor line below 01208 std::string oa(optarg); 01209 boost::tokenizer<boost::char_separator<char> > tok(oa, sep); 01210 01211 for(boost::tokenizer<boost::char_separator<char> >::const_iterator f = tok.begin(); 01212 f != tok.end(); ++f) { 01213 const std::string& token = *f; 01214 if (token == "none" ) { 01215 noneToken = true; 01216 } 01217 else if (token == "iobehavior" ) { 01218 pctx.config.setOption("ExternalLearningIOBehavior", 1); 01219 enableToken = true; 01220 } 01221 else if( token == "monotonicity" ) { 01222 pctx.config.setOption("ExternalLearningMonotonicity", 1); 01223 enableToken = true; 01224 } 01225 else if( token == "functionality" ) { 01226 pctx.config.setOption("ExternalLearningFunctionality", 1); 01227 enableToken = true; 01228 } 01229 else if( token == "linearity" ) { 01230 pctx.config.setOption("ExternalLearningLinearity", 1); 01231 enableToken = true; 01232 } 01233 else if( token == "neg" ) { 01234 pctx.config.setOption("ExternalLearningNeg", 1); 01235 enableToken = true; 01236 } 01237 else if( token == "user" ) { 01238 pctx.config.setOption("ExternalLearningUser", 1); 01239 enableToken = true; 01240 } 01241 else if( token == "generalize" ) { 01242 pctx.config.setOption("ExternalLearningGeneralize", 1); 01243 enableToken = true; 01244 } 01245 else { 01246 throw GeneralError("Unknown learning option: \"" + token + "\""); 01247 } 01248 } 01249 } 01250 else { 01251 // by default, turn on all external learning rules 01252 pctx.config.setOption("ExternalLearningIOBehavior", 1); 01253 pctx.config.setOption("ExternalLearningMonotonicity", 1); 01254 pctx.config.setOption("ExternalLearningFunctionality", 1); 01255 pctx.config.setOption("ExternalLearningLinearity", 1); 01256 pctx.config.setOption("ExternalLearningNeg", 1); 01257 pctx.config.setOption("ExternalLearningUser", 1); 01258 //pctx.config.setOption("ExternalLearningGeneralize", 1); // do not activate by default (it is mostly counterproductive) 01259 } 01260 if (noneToken && enableToken) { 01261 throw GeneralError("--extlearn: Value \"none\" cannot be used simultanously with other options"); 01262 } 01263 01264 pctx.config.setOption("ExternalLearning", noneToken ? 0 : 1); 01265 } 01266 01267 LOG(DBG, "External learning: " << pctx.config.getOption("ExternalLearning") << " [iobehavior: " << pctx.config.getOption("ExternalLearningIOBehavior") << " [monotonicity: " << pctx.config.getOption("ExternalLearningMonotonicity") << ", functionlity: " << pctx.config.getOption("ExternalLearningFunctionality") << ", linearity: " << pctx.config.getOption("ExternalLearningLinearity") << ", user-defined: " << pctx.config.getOption("ExternalLearningUser") << "]"); 01268 break; 01269 01270 case 19: 01271 01272 { 01273 pctx.config.setOption("AlwaysEvaluateAllExternalAtoms", 1); 01274 break; 01275 } 01276 01277 case 20: 01278 { 01279 std::string check(optarg); 01280 if( check == "explicit" ) { 01281 pctx.config.setOption("FLPCheck", 1); 01282 pctx.config.setOption("UFSCheck", 0); 01283 }else if( check == "ufs" ) 01284 { 01285 pctx.config.setOption("FLPCheck", 0); 01286 pctx.config.setOption("UFSCheck", 1); 01287 pctx.config.setOption("UFSCheckMonolithic", 0); 01288 pctx.config.setOption("UFSCheckAssumptionBased", 0); 01289 }else if( check == "ufsm" ) 01290 { 01291 pctx.config.setOption("FLPCheck", 0); 01292 pctx.config.setOption("UFSCheck", 1); 01293 pctx.config.setOption("UFSCheckMonolithic", 1); 01294 pctx.config.setOption("UFSCheckAssumptionBased", 0); 01295 01296 }else if( check == "aufs" ) 01297 { 01298 pctx.config.setOption("FLPCheck", 0); 01299 pctx.config.setOption("UFSCheck", 1); 01300 pctx.config.setOption("UFSCheckMonolithic", 0); 01301 pctx.config.setOption("UFSCheckAssumptionBased", 1); 01302 }else if( check == "aufsm" ) 01303 { 01304 pctx.config.setOption("FLPCheck", 0); 01305 pctx.config.setOption("UFSCheck", 1); 01306 pctx.config.setOption("UFSCheckMonolithic", 1); 01307 pctx.config.setOption("UFSCheckAssumptionBased", 1); 01308 }else if( check == "none" ) 01309 { 01310 pctx.config.setOption("FLPCheck", 0); 01311 pctx.config.setOption("UFSCheck", 0); 01312 } 01313 else { 01314 throw GeneralError("Invalid FLP check option: \"" + check + "\""); 01315 } 01316 01317 LOG(INFO,"FLP Check: " << pctx.config.getOption("FLPCheck") << "; UFS Check: " << pctx.config.getOption("UFSCheck")); 01318 } 01319 01320 break; 01321 01322 case 23: 01323 if (!optarg) { 01324 // use UFS-based learning 01325 pctx.config.setOption("UFSLearning", 1); 01326 pctx.config.setOption("UFSLearnStrategy", 2); 01327 } 01328 else { 01329 std::string learn(optarg); 01330 if (learn == "none") { 01331 pctx.config.setOption("UFSLearning", 0); 01332 } 01333 else if (learn == "reduct") { 01334 pctx.config.setOption("UFSLearning", 1); 01335 pctx.config.setOption("UFSLearnStrategy", 1); 01336 } 01337 else if (learn == "ufs") { 01338 pctx.config.setOption("UFSLearning", 1); 01339 pctx.config.setOption("UFSLearnStrategy", 2); 01340 } 01341 else { 01342 throw GeneralError("Unknown UFS Learning option: \"" + learn + "\""); 01343 } 01344 } 01345 break; 01346 01347 case 26: 01348 { 01349 std::string heur(optarg); 01350 if (heur == "always") { 01351 pctx.defaultExternalAtomEvaluationHeuristicsFactory.reset(new ExternalAtomEvaluationHeuristicsAlwaysFactory()); 01352 pctx.config.setOption("NoPropagator", 0); 01353 } 01354 else if (heur == "periodic") { 01355 pctx.defaultExternalAtomEvaluationHeuristicsFactory.reset(new ExternalAtomEvaluationHeuristicsPeriodicFactory()); 01356 pctx.config.setOption("NoPropagator", 0); 01357 } 01358 else if (heur == "inputcomplete") { 01359 pctx.defaultExternalAtomEvaluationHeuristicsFactory.reset(new ExternalAtomEvaluationHeuristicsInputCompleteFactory()); 01360 pctx.config.setOption("NoPropagator", 0); 01361 } 01362 else if (heur == "eacomplete") { 01363 pctx.defaultExternalAtomEvaluationHeuristicsFactory.reset(new ExternalAtomEvaluationHeuristicsEACompleteFactory()); 01364 pctx.config.setOption("NoPropagator", 0); 01365 } 01366 else if (heur == "post") { 01367 // here we evaluate only after the model candidate has been completed 01368 pctx.defaultExternalAtomEvaluationHeuristicsFactory.reset(new ExternalAtomEvaluationHeuristicsNeverFactory()); 01369 pctx.config.setOption("NoPropagator", 0); 01370 } 01371 else if (heur == "never") { 01372 // here we evaluate only after the model candidate has been completed 01373 // differently from post, even the propagator is diabled, thus also custom heuristics provided by external atoms cannot overwrite this behavior 01374 pctx.defaultExternalAtomEvaluationHeuristicsFactory.reset(new ExternalAtomEvaluationHeuristicsNeverFactory()); 01375 pctx.config.setOption("NoPropagator", 1); 01376 } 01377 else { 01378 throw GeneralError(std::string("Unknown external atom evaluation heuristic: \"") + heur + std::string("\"")); 01379 } 01380 } 01381 break; 01382 01383 case 27: 01384 { 01385 std::string heur(optarg); 01386 if (heur == "post") { 01387 pctx.unfoundedSetCheckHeuristicsFactory.reset(new UnfoundedSetCheckHeuristicsPostFactory()); 01388 pctx.config.setOption("UFSCheckHeuristics", 0); 01389 } 01390 else if (heur == "max") { 01391 pctx.unfoundedSetCheckHeuristicsFactory.reset(new UnfoundedSetCheckHeuristicsMaxFactory()); 01392 pctx.config.setOption("UFSCheckHeuristics", 1); 01393 } 01394 else if (heur == "periodic") { 01395 pctx.unfoundedSetCheckHeuristicsFactory.reset(new UnfoundedSetCheckHeuristicsPeriodicFactory()); 01396 pctx.config.setOption("UFSCheckHeuristics", 2); 01397 } 01398 else { 01399 throw GeneralError(std::string("Unknown UFS check heuristic: \"") + heur + std::string("\"")); 01400 } 01401 } 01402 break; 01403 01404 case 28: pctx.config.setOption("BenchmarkEAstderr",1); break; 01405 case 29: pctx.config.setOption("ExplicitFLPUnshift",1); break; 01406 01407 case 30: pctx.config.setOption("PrintLearnedNogoods",1); break; 01408 01409 case 31: pctx.config.setOption("NongroundNogoodInstantiation", 1); break; 01410 01411 case 32: 01412 { 01413 int queuesize = 5; 01414 try 01415 { 01416 if( optarg[0] == '=' ) 01417 queuesize = boost::lexical_cast<unsigned>(&optarg[1]); 01418 else 01419 queuesize = boost::lexical_cast<unsigned>(optarg); 01420 } 01421 catch(const boost::bad_lexical_cast&) { 01422 LOG(ERROR,"could not parse size of model queue '" << optarg << "' - using default=" << queuesize << "!"); 01423 } 01424 if (queuesize < 1) { 01425 throw GeneralError(std::string("Model queue size must be > 0")); 01426 } 01427 pctx.config.setOption("ModelQueueSize", queuesize); break; 01428 specifiedModelQueueSize = true; 01429 } 01430 break; 01431 01432 case 33: 01433 pctx.config.setOption("LiberalSafety", 1); 01434 break; 01435 01436 case 35: 01437 pctx.config.setOption("FLPDecisionCriterionHead", 0); 01438 pctx.config.setOption("FLPDecisionCriterionE", 0); 01439 break; 01440 01441 case 36: pctx.config.setStringOption("ClaspConfiguration",std::string(optarg)); break; 01442 01443 case 37: 01444 pctx.config.setOption("DumpStats",1); 01445 #if !defined(DLVHEX_BENCHMARK) 01446 throw std::runtime_error("you can only use --dumpstats if you configured with --enable-benchmark"); 01447 #endif 01448 break; 01449 01450 case 38: 01451 defiaux = true; 01452 01453 if (!optarg) { 01454 iaux = true; 01455 } 01456 else { 01457 if (std::string(optarg) == "true") iaux = true; 01458 else if (std::string(optarg) == "false") iaux = false; 01459 else throw GeneralError("Unknown option \"" + std::string(optarg) + "\" for iauxinaux"); 01460 } 01461 break; 01462 01463 case 39: 01464 pctx.config.setOption("UseConstantSpace",1); 01465 break; 01466 01467 case '?': 01468 config.pluginOptions.push_back(argv[optind - 1]); 01469 break; 01470 case 40: 01471 pctx.config.setOption("ClaspForceSingleThreaded", 1); 01472 break; 01473 01474 case 42: 01475 if (optarg) { 01476 std::string cycle(optarg); 01477 if (cycle == "all") { 01478 pctx.config.setOption("FLPDecisionCriterionE", 1); 01479 pctx.config.setOption("FLPDecisionCriterionEM", 1); 01480 pctx.config.setOption("FLPDecisionCriterionEMI", 1); 01481 pctx.config.setOption("FLPDecisionCriterionHead", 1); 01482 } 01483 else if (cycle == "head") { 01484 pctx.config.setOption("FLPDecisionCriterionE", 0); 01485 pctx.config.setOption("FLPDecisionCriterionEM", 0); 01486 pctx.config.setOption("FLPDecisionCriterionEMI", 0); 01487 pctx.config.setOption("FLPDecisionCriterionHead", 1); 01488 } 01489 else if (cycle == "e") { 01490 pctx.config.setOption("FLPDecisionCriterionE", 1); 01491 pctx.config.setOption("FLPDecisionCriterionEM", 0); 01492 pctx.config.setOption("FLPDecisionCriterionEMI", 0); 01493 pctx.config.setOption("FLPDecisionCriterionHead", 0); 01494 } 01495 else if (cycle == "em") { 01496 pctx.config.setOption("FLPDecisionCriterionE", 1); 01497 pctx.config.setOption("FLPDecisionCriterionEM", 1); 01498 pctx.config.setOption("FLPDecisionCriterionEMI", 0); 01499 pctx.config.setOption("FLPDecisionCriterionHead", 0); 01500 } 01501 else if (cycle == "emi") { 01502 pctx.config.setOption("FLPDecisionCriterionE", 1); 01503 pctx.config.setOption("FLPDecisionCriterionEM", 1); 01504 pctx.config.setOption("FLPDecisionCriterionEMI", 1); 01505 pctx.config.setOption("FLPDecisionCriterionHead", 0); 01506 } 01507 else if (cycle == "none") { 01508 pctx.config.setOption("FLPDecisionCriterionE", 0); 01509 pctx.config.setOption("FLPDecisionCriterionEM", 0); 01510 pctx.config.setOption("FLPDecisionCriterionEMI", 0); 01511 pctx.config.setOption("FLPDecisionCriterionHead", 0); 01512 } 01513 else { 01514 throw GeneralError(std::string("Unknown cycle type: \"" + cycle + "\"")); 01515 } 01516 } 01517 else { 01518 pctx.config.setOption("FLPDecisionCriterionE", 1); 01519 pctx.config.setOption("FLPDecisionCriterionHead", 1); 01520 } 01521 break; 01522 case 43: 01523 pctx.config.setOption("ClaspIncrementalInterpretationExtraction", 0); 01524 break; 01525 case 44: 01526 pctx.config.setOption("ClaspSingletonLoopNogoods", 0); 01527 break; 01528 case 45: 01529 pctx.config.setOption("ClaspInverseLiterals", 1); 01530 break; 01531 case 46: 01532 pctx.config.setOption("LegacyECycleDetection", 1); 01533 break; 01534 case 47: 01535 pctx.config.setOption("LazyUFSCheckerInitialization", 1); 01536 break; 01537 case 48: 01538 pctx.config.setOption("SupportSets", 1); 01539 pctx.config.setOption("ExternalLearningUser", 1); 01540 pctx.config.setOption("ExternalLearning", 1); 01541 // pctx.config.setOption("ForceGC", 1); 01542 pctx.config.setOption("LiberalSafety", 1); 01543 break; 01544 case 49: 01545 pctx.config.setOption("ForceGC", 1); 01546 pctx.config.setOption("LiberalSafety", 1); 01547 break; 01548 case 50: 01549 pctx.config.setOption("IncrementalGrounding", 1); 01550 break; 01551 case 52: 01552 pctx.config.setOption("LiberalSafety", 0); 01553 break; 01554 case 54: 01555 { 01556 int optmode = 0; 01557 try 01558 { 01559 if( optarg[0] == '=' ) 01560 optmode = boost::lexical_cast<unsigned>(&optarg[1]); 01561 else 01562 optmode = boost::lexical_cast<unsigned>(optarg); 01563 } 01564 catch(const boost::bad_lexical_cast&) { 01565 LOG(ERROR,"could not parse optmode '" << optarg << "' - using default"); 01566 } 01567 pctx.config.setOption("OptimizationTwoStep", optmode); 01568 forceoptmode = true; 01569 } 01570 break; 01571 case 55: 01572 { 01573 int deferval = 0; 01574 try 01575 { 01576 if( optarg[0] == '=' ) 01577 deferval = boost::lexical_cast<unsigned>(&optarg[1]); 01578 else 01579 deferval = boost::lexical_cast<unsigned>(optarg); 01580 } 01581 catch(const boost::bad_lexical_cast&) { 01582 LOG(ERROR,"claspdefernprop '" << optarg << "' does not specify an integer value"); 01583 } 01584 pctx.config.setOption("ClaspDeferNPropagations", deferval); 01585 } 01586 break; 01587 case 56: 01588 { 01589 int deferval = 0; 01590 try 01591 { 01592 if( optarg[0] == '=' ) 01593 deferval = boost::lexical_cast<unsigned>(&optarg[1]); 01594 else 01595 deferval = boost::lexical_cast<unsigned>(optarg); 01596 } 01597 catch(const boost::bad_lexical_cast&) { 01598 LOG(ERROR,"claspdefermsec '" << optarg << "' does not specify an integer value"); 01599 } 01600 pctx.config.setOption("ClaspDeferMaxTMilliseconds", deferval); 01601 } 01602 break; 01603 case 57: 01604 { 01605 pctx.config.setStringOption("DumpEANogoods", optarg); 01606 std::ofstream filev(pctx.config.getStringOption("DumpEANogoods").c_str(), std::ios_base::out); 01607 } 01608 break; 01609 case 58: 01610 { 01611 std::string heur(optarg); 01612 if (heur == "always") { 01613 pctx.config.setOption("MinimizeNogoods", 1); 01614 } 01615 else if (heur == "onconflict") { 01616 pctx.config.setOption("MinimizeNogoods", 1); 01617 pctx.config.setOption("MinimizeNogoodsOnConflict", 1); 01618 } 01619 else if (heur == "alwaysopt") { 01620 pctx.config.setOption("MinimizeNogoods", 1); 01621 pctx.config.setOption("MinimizeNogoodsOpt", 1); 01622 } 01623 else if (heur == "onconflictopt") { 01624 pctx.config.setOption("MinimizeNogoods", 1); 01625 pctx.config.setOption("MinimizeNogoodsOpt", 1); 01626 pctx.config.setOption("MinimizeNogoodsOnConflict", 1); 01627 } 01628 else { 01629 throw GeneralError(std::string("Unknown value for nogood minimization: \"") + heur + std::string("\"")); 01630 } 01631 } 01632 break; 01633 case 59: 01634 { 01635 int minval = 0; 01636 try 01637 { 01638 if( optarg[0] == '=' ) 01639 minval = boost::lexical_cast<unsigned>(&optarg[1]); 01640 else 01641 minval = boost::lexical_cast<unsigned>(optarg); 01642 } 01643 catch(const boost::bad_lexical_cast&) { 01644 LOG(ERROR,"minimizesize '" << optarg << "' does not specify an integer value"); 01645 } 01646 pctx.config.setOption("MinimizationSize", minval); 01647 } 01648 break; 01649 case 60: 01650 { 01651 std::string arg(optarg); 01652 if (arg.find(',', 0) == std::string::npos) throw GeneralError(std::string("Argument of \"--csvinput\" must be of type \"PREDICATE,FILENAME\"")); 01653 std::string pred = arg.substr(0, arg.find(',', 0)); 01654 std::string filename = arg.substr(arg.find(',', 0) + 1); 01655 pctx.inputProvider->addCSVFileInput(pred, filename); 01656 } 01657 break; 01658 case 61: 01659 { 01660 std::string pred(optarg); 01661 pctx.modelCallbacks.push_back(ModelCallbackPtr(new CSVAnswerSetPrinterCallback(pctx, pred))); 01662 } 01663 break; 01664 case 62: 01665 { 01666 pctx.config.setOption("NoOuterExternalAtoms", 1); 01667 } 01668 break; 01669 case 64: 01670 { 01671 pctx.config.setOption("UnitInconsistencyAnalysis", 1); 01672 pctx.config.setOption("TransUnitLearning", 1); 01673 pctx.config.setOption("ForceGC", 1); 01674 pctx.config.setOption("LiberalSafety", 1); 01675 pctx.config.setOption("NoOuterExternalAtoms", 1); 01676 } 01677 break; 01678 case 65: 01679 { 01680 pctx.config.setOption("ExternalAtomVerificationFromLearnedNogoods", 1); 01681 } 01682 break; 01683 case 66: 01684 { 01685 pctx.config.setOption("WaitOnModel", 1); 01686 } 01687 break; 01688 case 67: 01689 { 01690 pctx.config.setOption("SupportSets", 1); 01691 pctx.config.setOption("ExternalSourceInlining", 1); 01692 } 01693 } 01694 } 01695 01696 // global constraints 01697 if (pctx.config.getOption("UFSCheck") && !pctx.config.getOption("GenuineSolver")) { 01698 // if solver was not set by user, disable it silently, otherwise print a warning 01699 if (!solverSet) { 01700 DBGLOG(WARNING, "Unfounded Set Check is only supported for genuine solvers; will behave like flpcheck=explicit"); 01701 } 01702 else { 01703 LOG(WARNING, "Unfounded Set Check is only supported for genuine solvers; will behave like flpcheck=explicit"); 01704 } 01705 pctx.config.setOption("FLPCheck", 1); 01706 pctx.config.setOption("UFSCheck", 0); 01707 } 01708 if (pctx.config.getOption("LiberalSafety") && !pctx.config.getOption("GenuineSolver")) { 01709 // if solver was not set by user, disable it silently, otherwise print a warning 01710 if (!solverSet) { 01711 DBGLOG(WARNING, "Liberal safety is only supported for genuine solvers, will disable it"); 01712 } 01713 else { 01714 LOG(WARNING, "Liberal safety is only supported for genuine solvers, will disable it"); 01715 } 01716 pctx.config.setOption("LiberalSafety", 0); 01717 } 01718 if (specifiedModelQueueSize && pctx.config.getOption("GenuineSolver") <= 2) { 01719 LOG(WARNING, "Model caching (modelqueuesize) is only compatible with clasp backend"); 01720 } 01721 if (pctx.config.getOption("GenuineSolver") || pctx.config.getOption("LiberalSafety") || heuristicMonolithic) { 01722 pctx.config.setOption("IncludeAuxInputInAuxiliaries", 1); 01723 } 01724 if (defiaux) { 01725 pctx.config.setOption("IncludeAuxInputInAuxiliaries", iaux); 01726 } 01727 if (!pctx.config.getOption("GenuineSolver") && pctx.config.getOption("ExternalLearning")) { 01728 // if solver was not set by user, disable it silently, otherwise print a warning 01729 if (!solverSet) { 01730 DBGLOG(WARNING, "Cannot use external learning with non-genuine solver, will disable it"); 01731 } 01732 else { 01733 LOG(WARNING, "Cannot use external learning with non-genuine solver, will disable it"); 01734 } 01735 pctx.config.setOption("ExternalLearning", 0); 01736 01737 } 01738 bool usingClaspBackend = (pctx.config.getOption("GenuineSolver") == 3 || pctx.config.getOption("GenuineSolver") == 4); 01739 if( !forceoptmode && heuristicMonolithic && usingClaspBackend ) { 01740 // we can use this in a safe way if we use a monolithic evaluation unit 01741 // we can use this with the clasp backend (the other solver does not honor setOptimum() calls) 01742 // TODO we can also use this if we have all weight constraints in one evaluation unit, this can be detected automatically 01743 pctx.config.setOption("OptimizationTwoStep", 1); 01744 } 01745 // We cannot use strong safety if we treat all outer external atoms as inner ones. 01746 // We support two types of safety (strong and liberal) and two grounding approaches (decomposition-based and fixpoint-based). The two dimensions are related as follows: 01747 // - decomposition-based grounding is made for strong safety (it cannot handle liberally safe programs) 01748 // - fixpoint-based grounding is made for liberal safety (but can also handle strongly safe programs which are a special case of liberally safe ones) 01749 // Currently there are no separate options for the two dimensions: --strongsafety and --liberalsafety switch both the safety concept and the grounding approach (fixpoint-based with --liberalsafety and decomposition-based for --strongsafety). 01750 // Treating outer external atoms as inner ones does not destroy strong safety (because the structure of the program does not change) but destroys correctness of the decomposition-based grounder even for strongly safe programs, 01751 // while the fixpoint-based grounding approach is still correct (both for strongly and for liberally safe programs). 01752 // Thus, we can only handle outer external atoms as inner ones if --liberalsafety is used since then also the fixpoint-based grounding approach is used 01753 // (in principle, switching only the grounding approach to fixpoint-based but still using strong safety is possible but not implemented). 01754 if (!pctx.config.getOption("LiberalSafety") && pctx.config.getOption("NoOuterExternalAtoms")){ 01755 throw GeneralError("Option --noouterexternalatoms can only be used with --liberalsafety"); 01756 } 01757 01758 // configure plugin path 01759 configurePluginPath(config.optionPlugindir); 01760 01761 // check input files (stdin, file, or URI) 01762 01763 // stdin requested, append it first 01764 if( std::string(argv[optind - 1]) == "--" ) 01765 pctx.inputProvider->addStreamInput(std::cin, "<stdin>"); 01766 01767 // collect further filenames/URIs 01768 // if we use dlvdb, manage .typ files 01769 for (int i = optind; i < argc; ++i) { 01770 std::string arg(argv[i]); 01771 if( arg.size() > 4 && arg.substr(arg.size()-4) == ".typ" ) { 01772 #if defined(HAVE_DLVDB) 01773 boost::shared_ptr<ASPSolver::DLVDBSoftware::Configuration> ptr = 01774 boost::dynamic_pointer_cast<ASPSolver::DLVDBSoftware::Configuration>(pctx.getASPSoftware()); 01775 if( ptr == 0 ) 01776 throw GeneralError(".typ files can only be used if dlvdb backend is used"); 01777 01778 if( !ptr->options.typFile.empty() ) 01779 throw GeneralError("cannot use more than one .typ file with dlvdb"); 01780 01781 ptr->options.typFile = arg; 01782 #endif 01783 } 01784 #ifdef HAEV_LIBCURL 01785 else if( arg.find("http://") == 0 ) { 01786 pctx.inputProvider->addURLInput(arg); 01787 } 01788 #endif 01789 else { 01790 pctx.inputProvider->addFileInput(arg); 01791 } 01792 } 01793 } 01794 01795 01796 void configurePluginPath(std::string& userPlugindir) 01797 { 01798 #ifdef WIN32 01799 bool reset = false; 01800 if( !userPlugindir.empty() && userPlugindir[0] == '!' ) { 01801 reset = true; 01802 if( userPlugindir.size() > 2 && userPlugindir[1] == ';' ) 01803 userPlugindir.erase(0,2); 01804 else 01805 userPlugindir.erase(0,1); 01806 } 01807 01808 std::stringstream searchpath; 01809 01810 if( !userPlugindir.empty() ) 01811 searchpath << userPlugindir << ';'; 01812 01813 #ifdef LOCAL_PLUGIN_DIR 01814 reset = true; 01815 searchpath << LOCAL_PLUGIN_DIR << ';'; 01816 #endif 01817 01818 if( !reset ) { 01819 // add LD_LIBRARY_PATH 01820 const char *envld = ::getenv("LD_LIBRARY_PATH"); 01821 if( envld ) { 01822 searchpath << envld << ";"; 01823 } 01824 01825 #ifdef USER_PLUGIN_DIR 01826 const char* homedir = ::getenv("USERPROFILE"); 01827 if (!!homedir) searchpath << homedir << "/" USER_PLUGIN_DIR << ';'; 01828 #endif 01829 #ifdef SYS_PLUGIN_DIR 01830 searchpath << SYS_PLUGIN_DIR; 01831 #endif 01832 } 01833 userPlugindir = searchpath.str(); 01834 #elif POSIX 01835 bool reset = false; 01836 if( !userPlugindir.empty() && userPlugindir[0] == '!' ) { 01837 reset = true; 01838 if( userPlugindir.size() > 2 && userPlugindir[1] == ':' ) 01839 userPlugindir.erase(0,2); 01840 else 01841 userPlugindir.erase(0,1); 01842 } 01843 01844 std::stringstream searchpath; 01845 01846 if( !userPlugindir.empty() ) 01847 searchpath << userPlugindir << ':'; 01848 01849 #ifdef LOCAL_PLUGIN_DIR 01850 reset = true; 01851 searchpath << LOCAL_PLUGIN_DIR << ':'; 01852 #endif 01853 01854 if( !reset ) { 01855 // add LD_LIBRARY_PATH 01856 const char *envld = ::getenv("LD_LIBRARY_PATH"); 01857 if( envld ) { 01858 searchpath << envld << ":"; 01859 } 01860 01861 const char* homedir = ::getpwuid(::geteuid())->pw_dir; 01862 searchpath << homedir << "/" USER_PLUGIN_DIR << ':' << SYS_PLUGIN_DIR; 01863 } 01864 userPlugindir = searchpath.str(); 01865 #else 01866 #error Either POSIX or WIN32 must be defined 01867 #endif 01868 } 01869 01870 01871 // vim:expandtab:ts=4:sw=4: 01872 // mode: C++ 01873 // End: 01874